mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 769742 - Account for nsSVGOuterSVGFrames' border/padding offset by giving nsSVGOuterSVGFrame an anonymous child to wrap its real children. r=roc.
This commit is contained in:
parent
09ff7e2e99
commit
f410406b60
@ -1750,6 +1750,7 @@ GK_ATOM(svgLinearGradientFrame, "SVGLinearGradientFrame")
|
||||
GK_ATOM(svgMarkerFrame, "SVGMarkerFrame")
|
||||
GK_ATOM(svgMaskFrame, "SVGMaskFrame")
|
||||
GK_ATOM(svgOuterSVGFrame, "SVGOuterSVGFrame")
|
||||
GK_ATOM(svgOuterSVGAnonChildFrame, "SVGOuterSVGAnonChildFrame")
|
||||
GK_ATOM(svgPathGeometryFrame, "SVGPathGeometryFrame")
|
||||
GK_ATOM(svgPatternFrame, "SVGPatternFrame")
|
||||
GK_ATOM(svgRadialGradientFrame, "SVGRadialGradientFrame")
|
||||
|
@ -139,6 +139,8 @@ NS_NewHTMLVideoFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
nsIFrame*
|
||||
NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
nsIFrame*
|
||||
NS_NewSVGOuterSVGAnonChildFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
nsIFrame*
|
||||
NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
nsIFrame*
|
||||
NS_NewSVGPathGeometryFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
@ -2407,25 +2409,30 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle
|
||||
#endif
|
||||
if (aDocElement->IsSVG()) {
|
||||
if (aDocElement->Tag() == nsGkAtoms::svg) {
|
||||
contentFrame = NS_NewSVGOuterSVGFrame(mPresShell, styleContext);
|
||||
if (NS_UNLIKELY(!contentFrame)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
InitAndRestoreFrame(state, aDocElement,
|
||||
state.GetGeometricParent(display,
|
||||
mDocElementContainingBlock),
|
||||
nsnull, contentFrame);
|
||||
// We're going to call the right function ourselves, so no need to give a
|
||||
// function to this FrameConstructionData.
|
||||
|
||||
// XXXbz on the other hand, if we converted this whole function to
|
||||
// FrameConstructionData/Item, then we'd need the right function
|
||||
// here... but would probably be able to get away with less code in this
|
||||
// function in general.
|
||||
// Use a null PendingBinding, since our binding is not in fact pending.
|
||||
static const FrameConstructionData rootSVGData = FCDATA_DECL(0, nsnull);
|
||||
nsRefPtr<nsStyleContext> extraRef(styleContext);
|
||||
FrameConstructionItem item(&rootSVGData, aDocElement,
|
||||
aDocElement->Tag(), kNameSpaceID_SVG,
|
||||
nsnull, extraRef.forget(), true);
|
||||
|
||||
// AddChild takes care of transforming the frame tree for fixed-pos
|
||||
// or abs-pos situations
|
||||
nsFrameItems frameItems;
|
||||
rv = state.AddChild(contentFrame, frameItems, aDocElement,
|
||||
styleContext, mDocElementContainingBlock);
|
||||
if (NS_FAILED(rv) || frameItems.IsEmpty()) {
|
||||
rv = ConstructOuterSVG(state, item, mDocElementContainingBlock,
|
||||
styleContext->GetStyleDisplay(),
|
||||
frameItems, &contentFrame);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
if (!contentFrame || frameItems.IsEmpty())
|
||||
return NS_ERROR_FAILURE;
|
||||
*aNewFrame = frameItems.FirstChild();
|
||||
processChildren = true;
|
||||
NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -2498,8 +2505,9 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle
|
||||
// Still need to process the child content
|
||||
nsFrameItems childItems;
|
||||
|
||||
NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame),
|
||||
"Only XUL and SVG frames should reach here");
|
||||
NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame) &&
|
||||
!contentFrame->IsFrameOfType(nsIFrame::eSVG),
|
||||
"Only XUL frames should reach here");
|
||||
// Use a null PendingBinding, since our binding is not in fact pending.
|
||||
ProcessChildren(state, aDocElement, styleContext, contentFrame, true,
|
||||
childItems, false, nsnull);
|
||||
@ -4702,6 +4710,82 @@ nsCSSFrameConstructor::FindMathMLData(Element* aElement,
|
||||
ArrayLength(sMathMLData));
|
||||
}
|
||||
|
||||
|
||||
// Construct an nsSVGOuterSVGFrame, the anonymous child that wraps its real
|
||||
// children, and its descendant frames.
|
||||
nsresult
|
||||
nsCSSFrameConstructor::ConstructOuterSVG(nsFrameConstructorState& aState,
|
||||
FrameConstructionItem& aItem,
|
||||
nsIFrame* aParentFrame,
|
||||
const nsStyleDisplay* aDisplay,
|
||||
nsFrameItems& aFrameItems,
|
||||
nsIFrame** aNewFrame)
|
||||
{
|
||||
nsIContent* const content = aItem.mContent;
|
||||
nsStyleContext* const styleContext = aItem.mStyleContext;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Create the nsSVGOuterSVGFrame:
|
||||
nsIFrame* newFrame = NS_NewSVGOuterSVGFrame(mPresShell, styleContext);
|
||||
|
||||
nsIFrame* geometricParent =
|
||||
aState.GetGeometricParent(styleContext->GetStyleDisplay(),
|
||||
aParentFrame);
|
||||
|
||||
InitAndRestoreFrame(aState, content, geometricParent, nsnull, newFrame);
|
||||
|
||||
// Create the pseudo SC for the anonymous wrapper child as a child of the SC:
|
||||
nsRefPtr<nsStyleContext> scForAnon;
|
||||
scForAnon = mPresShell->StyleSet()->
|
||||
ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozSVGOuterSVGAnonChild,
|
||||
styleContext);
|
||||
|
||||
// Create the anonymous inner wrapper frame
|
||||
nsIFrame* innerFrame = NS_NewSVGOuterSVGAnonChildFrame(mPresShell, scForAnon);
|
||||
|
||||
if (!innerFrame) {
|
||||
newFrame->Destroy();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
InitAndRestoreFrame(aState, content, newFrame, nsnull, innerFrame);
|
||||
|
||||
// Put the newly created frames into the right child list
|
||||
SetInitialSingleChild(newFrame, innerFrame);
|
||||
|
||||
rv = aState.AddChild(newFrame, aFrameItems, content, styleContext,
|
||||
aParentFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mRootElementFrame) {
|
||||
// The frame we're constructing will be the root element frame.
|
||||
// Set mRootElementFrame before processing children.
|
||||
mRootElementFrame = newFrame;
|
||||
}
|
||||
|
||||
nsFrameItems childItems;
|
||||
|
||||
// Process children
|
||||
if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
|
||||
rv = ConstructFramesFromItemList(aState, aItem.mChildItems,
|
||||
innerFrame, childItems);
|
||||
} else {
|
||||
rv = ProcessChildren(aState, content, styleContext, innerFrame,
|
||||
true, childItems, false, aItem.mPendingBinding);
|
||||
}
|
||||
// XXXbz what about cleaning up?
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Set the inner wrapper frame's initial primary list
|
||||
innerFrame->SetInitialChildList(kPrincipalList, childItems);
|
||||
|
||||
*aNewFrame = newFrame;
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Only outer <svg> elements can be floated or positioned. All other SVG
|
||||
// should be in-flow.
|
||||
#define SIMPLE_SVG_FCDATA(_func) \
|
||||
@ -4789,8 +4873,7 @@ nsCSSFrameConstructor::FindSVGData(Element* aElement,
|
||||
// and do the PassesConditionalProcessingTests call in
|
||||
// nsSVGOuterSVGFrame::Init.
|
||||
static const FrameConstructionData sOuterSVGData =
|
||||
FCDATA_DECL(FCDATA_SKIP_ABSPOS_PUSH | FCDATA_DISALLOW_GENERATED_CONTENT,
|
||||
NS_NewSVGOuterSVGFrame);
|
||||
FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructOuterSVG);
|
||||
return &sOuterSVGData;
|
||||
}
|
||||
|
||||
|
@ -1351,6 +1351,18 @@ private:
|
||||
nsStyleContext* aStyleContext);
|
||||
|
||||
// SVG - rods
|
||||
/**
|
||||
* Construct an nsSVGOuterSVGFrame, the anonymous child that wraps its real
|
||||
* children, and its descendant frames. This is the FrameConstructionData
|
||||
* callback used for the job.
|
||||
*/
|
||||
nsresult ConstructOuterSVG(nsFrameConstructorState& aState,
|
||||
FrameConstructionItem& aItem,
|
||||
nsIFrame* aParentFrame,
|
||||
const nsStyleDisplay* aDisplay,
|
||||
nsFrameItems& aFrameItems,
|
||||
nsIFrame** aNewFrame);
|
||||
|
||||
static const FrameConstructionData* FindSVGData(Element* aElement,
|
||||
nsIAtom* aTag,
|
||||
PRInt32 aNameSpaceID,
|
||||
|
@ -147,6 +147,7 @@ FRAME_ID(nsSVGLinearGradientFrame)
|
||||
FRAME_ID(nsSVGMarkerFrame)
|
||||
FRAME_ID(nsSVGMaskFrame)
|
||||
FRAME_ID(nsSVGOuterSVGFrame)
|
||||
FRAME_ID(nsSVGOuterSVGAnonChildFrame)
|
||||
FRAME_ID(nsSVGPaintServerFrame)
|
||||
FRAME_ID(nsSVGPathGeometryFrame)
|
||||
FRAME_ID(nsSVGPatternFrame)
|
||||
|
@ -81,4 +81,5 @@ CSS_ANON_BOX(moztreeprogressmeter, ":-moz-tree-progressmeter")
|
||||
CSS_ANON_BOX(moztreedropfeedback, ":-moz-tree-drop-feedback")
|
||||
#endif
|
||||
|
||||
CSS_ANON_BOX(mozSVGOuterSVGAnonChild, ":-moz-svg-outer-svg-anon-child")
|
||||
CSS_ANON_BOX(mozSVGForeignContent, ":-moz-svg-foreign-content")
|
||||
|
@ -391,29 +391,32 @@ nsSVGOuterSVGFrame::Reflow(nsPresContext* aPresContext,
|
||||
NotifyViewportOrTransformChanged(changeBits);
|
||||
}
|
||||
|
||||
nsSVGOuterSVGAnonChildFrame *anonKid =
|
||||
static_cast<nsSVGOuterSVGAnonChildFrame*>(GetFirstPrincipalChild());
|
||||
|
||||
if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
|
||||
// Now that we've marked the necessary children as dirty, call
|
||||
// UpdateBounds() on them:
|
||||
|
||||
mCallingUpdateBounds = true;
|
||||
|
||||
if (!(mState & NS_STATE_SVG_NONDISPLAY_CHILD)) {
|
||||
nsIFrame* kid = mFrames.FirstChild();
|
||||
while (kid) {
|
||||
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
|
||||
if (SVGFrame && !(kid->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
|
||||
SVGFrame->UpdateBounds();
|
||||
}
|
||||
kid = kid->GetNextSibling();
|
||||
}
|
||||
}
|
||||
// Update the mRects and visual overflow rects of all our descendants,
|
||||
// including our anonymous wrapper kid:
|
||||
anonKid->UpdateBounds();
|
||||
NS_ABORT_IF_FALSE(!anonKid->GetNextSibling(),
|
||||
"We should have one anonymous child frame wrapping our real children");
|
||||
|
||||
mCallingUpdateBounds = false;
|
||||
}
|
||||
|
||||
// Make sure we scroll if we're too big:
|
||||
// XXX Use the bounding box of our descendants? (See bug 353460 comment 14.)
|
||||
aDesiredSize.SetOverflowAreasToDesiredBounds();
|
||||
FinishAndStoreOverflow(&aDesiredSize);
|
||||
|
||||
// Set our anonymous kid's offset from our border box:
|
||||
anonKid->SetPosition(GetContentRectRelativeToSelf().TopLeft());
|
||||
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("exit nsSVGOuterSVGFrame::Reflow: size=%d,%d",
|
||||
aDesiredSize.width, aDesiredSize.height));
|
||||
@ -471,8 +474,11 @@ nsDisplayOuterSVG::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
nsPoint rectCenter(rectAtOrigin.x + rectAtOrigin.width / 2,
|
||||
rectAtOrigin.y + rectAtOrigin.height / 2);
|
||||
|
||||
nsSVGOuterSVGAnonChildFrame *anonKid =
|
||||
static_cast<nsSVGOuterSVGAnonChildFrame*>(
|
||||
outerSVGFrame->GetFirstPrincipalChild());
|
||||
nsIFrame* frame = nsSVGUtils::HitTestChildren(
|
||||
outerSVGFrame, rectCenter + outerSVGFrame->GetPosition() -
|
||||
anonKid, rectCenter + outerSVGFrame->GetPosition() -
|
||||
outerSVGFrame->GetContentRect().TopLeft());
|
||||
if (frame) {
|
||||
aOutFrames->AppendElement(frame);
|
||||
@ -546,8 +552,8 @@ nsSVGOuterSVGFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
||||
// make sure our cached transform matrix gets (lazily) updated
|
||||
mCanvasTM = nsnull;
|
||||
|
||||
nsSVGUtils::NotifyChildrenOfSVGChange(
|
||||
this, aAttribute == nsGkAtoms::viewBox ?
|
||||
nsSVGUtils::NotifyChildrenOfSVGChange(GetFirstPrincipalChild(),
|
||||
aAttribute == nsGkAtoms::viewBox ?
|
||||
TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED : TRANSFORM_CHANGED);
|
||||
|
||||
static_cast<nsSVGSVGElement*>(mContent)->ChildrenOnlyTransformChanged();
|
||||
@ -676,7 +682,38 @@ nsSVGOuterSVGFrame::NotifyViewportOrTransformChanged(PRUint32 aFlags)
|
||||
}
|
||||
}
|
||||
|
||||
nsSVGUtils::NotifyChildrenOfSVGChange(this, aFlags);
|
||||
nsSVGUtils::NotifyChildrenOfSVGChange(GetFirstPrincipalChild(), aFlags);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISVGChildFrame methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGOuterSVGFrame::PaintSVG(nsRenderingContext* aContext,
|
||||
const nsIntRect *aDirtyRect)
|
||||
{
|
||||
NS_ASSERTION(GetFirstPrincipalChild()->GetType() ==
|
||||
nsGkAtoms::svgOuterSVGAnonChildFrame &&
|
||||
!GetFirstPrincipalChild()->GetNextSibling(),
|
||||
"We should have a single, anonymous, child");
|
||||
nsSVGOuterSVGAnonChildFrame *anonKid =
|
||||
static_cast<nsSVGOuterSVGAnonChildFrame*>(GetFirstPrincipalChild());
|
||||
return anonKid->PaintSVG(aContext, aDirtyRect);
|
||||
}
|
||||
|
||||
SVGBBox
|
||||
nsSVGOuterSVGFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
NS_ASSERTION(GetFirstPrincipalChild()->GetType() ==
|
||||
nsGkAtoms::svgOuterSVGAnonChildFrame &&
|
||||
!GetFirstPrincipalChild()->GetNextSibling(),
|
||||
"We should have a single, anonymous, child");
|
||||
// We must defer to our child so that we don't include our
|
||||
// content->PrependLocalTransformsTo() transforms.
|
||||
nsSVGOuterSVGAnonChildFrame *anonKid =
|
||||
static_cast<nsSVGOuterSVGAnonChildFrame*>(GetFirstPrincipalChild());
|
||||
return anonKid->GetBBoxContribution(aToBBoxUserspace, aFlags);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -705,24 +742,6 @@ nsSVGOuterSVGFrame::GetCanvasTM(PRUint32 aFor)
|
||||
return *mCanvasTM;
|
||||
}
|
||||
|
||||
bool
|
||||
nsSVGOuterSVGFrame::HasChildrenOnlyTransform(gfxMatrix *aTransform) const
|
||||
{
|
||||
nsSVGSVGElement *content = static_cast<nsSVGSVGElement*>(mContent);
|
||||
|
||||
bool hasTransform = content->HasChildrenOnlyTransform();
|
||||
|
||||
if (hasTransform && aTransform) {
|
||||
// Outer-<svg> doesn't use x/y, so we can pass eChildToUserSpace here.
|
||||
gfxMatrix identity;
|
||||
*aTransform =
|
||||
content->PrependLocalTransformsTo(identity,
|
||||
nsSVGElement::eChildToUserSpace);
|
||||
}
|
||||
|
||||
return hasTransform;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation helpers
|
||||
|
||||
@ -777,3 +796,55 @@ nsSVGOuterSVGFrame::VerticalScrollbarNotNeeded() const
|
||||
mLengthAttributes[nsSVGSVGElement::HEIGHT];
|
||||
return height.IsPercentage() && height.GetBaseValInSpecifiedUnits() <= 100;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation of nsSVGOuterSVGAnonChildFrame
|
||||
|
||||
nsIFrame*
|
||||
NS_NewSVGOuterSVGAnonChildFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext)
|
||||
{
|
||||
return new (aPresShell) nsSVGOuterSVGAnonChildFrame(aContext);
|
||||
}
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsSVGOuterSVGAnonChildFrame)
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHODIMP
|
||||
nsSVGOuterSVGAnonChildFrame::Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aParent->GetType() == nsGkAtoms::svgOuterSVGFrame,
|
||||
"Unexpected parent");
|
||||
return nsSVGOuterSVGAnonChildFrameBase::Init(aContent, aParent, aPrevInFlow);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsIAtom *
|
||||
nsSVGOuterSVGAnonChildFrame::GetType() const
|
||||
{
|
||||
return nsGkAtoms::svgOuterSVGAnonChildFrame;
|
||||
}
|
||||
|
||||
bool
|
||||
nsSVGOuterSVGAnonChildFrame::HasChildrenOnlyTransform(gfxMatrix *aTransform) const
|
||||
{
|
||||
// We must claim our nsSVGOuterSVGFrame's children-only transforms as our own
|
||||
// so that the children we are used to wrap are transformed properly.
|
||||
|
||||
nsSVGSVGElement *content = static_cast<nsSVGSVGElement*>(mContent);
|
||||
|
||||
bool hasTransform = content->HasChildrenOnlyTransform();
|
||||
|
||||
if (hasTransform && aTransform) {
|
||||
// Outer-<svg> doesn't use x/y, so we can pass eChildToUserSpace here.
|
||||
gfxMatrix identity;
|
||||
*aTransform =
|
||||
content->PrependLocalTransformsTo(identity,
|
||||
nsSVGElement::eChildToUserSpace);
|
||||
}
|
||||
|
||||
return hasTransform;
|
||||
}
|
||||
|
@ -76,6 +76,15 @@ public:
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType);
|
||||
|
||||
virtual nsIFrame* GetContentInsertionFrame() {
|
||||
// Any children must be added to our single anonymous inner frame kid.
|
||||
NS_ABORT_IF_FALSE(GetFirstPrincipalChild() &&
|
||||
GetFirstPrincipalChild()->GetType() ==
|
||||
nsGkAtoms::svgOuterSVGAnonChildFrame,
|
||||
"Where is our anonymous child?");
|
||||
return GetFirstPrincipalChild()->GetContentInsertionFrame();
|
||||
}
|
||||
|
||||
virtual bool IsSVGTransformed(gfxMatrix *aOwnTransform,
|
||||
gfxMatrix *aFromParentTransform) const {
|
||||
// Outer-<svg> can transform its children with viewBox, currentScale and
|
||||
@ -86,10 +95,23 @@ public:
|
||||
// nsISVGSVGFrame interface:
|
||||
virtual void NotifyViewportOrTransformChanged(PRUint32 aFlags);
|
||||
|
||||
// nsISVGChildFrame methods:
|
||||
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
|
||||
const nsIntRect *aDirtyRect);
|
||||
|
||||
virtual SVGBBox GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
|
||||
PRUint32 aFlags);
|
||||
|
||||
// nsSVGContainerFrame methods:
|
||||
virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
|
||||
|
||||
virtual bool HasChildrenOnlyTransform(gfxMatrix *aTransform) const;
|
||||
virtual bool HasChildrenOnlyTransform(gfxMatrix *aTransform) const {
|
||||
// Our anonymous wrapper child must claim our children-only transforms as
|
||||
// its own so that our real children (the frames it wraps) are transformed
|
||||
// by them, and we must pretend we don't have any children-only transforms
|
||||
// so that our anonymous child is _not_ transformed by them.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true only if the height is unspecified (defaulting to 100%) or else
|
||||
@ -124,4 +146,81 @@ protected:
|
||||
bool mIsRootContent;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsSVGOuterSVGAnonChildFrame class
|
||||
|
||||
typedef nsSVGDisplayContainerFrame nsSVGOuterSVGAnonChildFrameBase;
|
||||
|
||||
/**
|
||||
* nsSVGOuterSVGFrames have a single direct child that is an instance of this
|
||||
* class, and which is used to wrap their real child frames. Such anonymous
|
||||
* wrapper frames created from this class exist because SVG frames need their
|
||||
* GetPosition() offset to be their offset relative to "user space" (in app
|
||||
* units) so that they can play nicely with nsDisplayTransform. This is fine
|
||||
* for all SVG frames except for direct children of an nsSVGOuterSVGFrame,
|
||||
* since an nsSVGOuterSVGFrame can have CSS border and padding (unlike other
|
||||
* SVG frames). The direct children can't include the offsets due to any such
|
||||
* border/padding in their mRects since that would break nsDisplayTransform,
|
||||
* but not including these offsets would break other parts of the Mozilla code
|
||||
* that assume a frame's mRect contains its border-box-to-parent-border-box
|
||||
* offset, in particular nsIFrame::GetOffsetTo and the functions that depend on
|
||||
* it. Wrapping an nsSVGOuterSVGFrame's children in an instance of this class
|
||||
* with its GetPosition() set to its nsSVGOuterSVGFrame's border/padding offset
|
||||
* keeps both nsDisplayTransform and nsIFrame::GetOffsetTo happy.
|
||||
*
|
||||
* The reason that this class inherit from nsSVGDisplayContainerFrame rather
|
||||
* than simply from nsContainerFrame is so that we can avoid having special
|
||||
* handling for these inner wrappers in multiple parts of the SVG code. For
|
||||
* example, the implementations of IsSVGTransformed and GetCanvasTM assume
|
||||
* nsSVGContainerFrame instances all the way up to the nsSVGOuterSVGFrame.
|
||||
*/
|
||||
class nsSVGOuterSVGAnonChildFrame
|
||||
: public nsSVGOuterSVGAnonChildFrameBase
|
||||
{
|
||||
friend nsIFrame*
|
||||
NS_NewSVGOuterSVGAnonChildFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
|
||||
nsSVGOuterSVGAnonChildFrame(nsStyleContext* aContext)
|
||||
: nsSVGOuterSVGAnonChildFrameBase(aContext)
|
||||
{}
|
||||
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow);
|
||||
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const {
|
||||
return MakeFrameName(NS_LITERAL_STRING("SVGOuterSVGAnonChild"), aResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the "type" of the frame
|
||||
*
|
||||
* @see nsGkAtoms::svgOuterSVGAnonChildFrame
|
||||
*/
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
virtual bool IsSVGTransformed(gfxMatrix *aOwnTransform,
|
||||
gfxMatrix *aFromParentTransform) const {
|
||||
// Outer-<svg> can transform its children with viewBox, currentScale and
|
||||
// currentTranslate, but it itself is not transformed by _SVG_ transforms.
|
||||
return false;
|
||||
}
|
||||
|
||||
// nsSVGContainerFrame methods:
|
||||
virtual gfxMatrix GetCanvasTM(PRUint32 aFor) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
virtual bool HasChildrenOnlyTransform(gfxMatrix *aTransform) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -703,7 +703,6 @@ nsSVGUtils::InvalidateBounds(nsIFrame *aFrame, bool aDuringUpdate,
|
||||
|
||||
NS_ASSERTION(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG,
|
||||
"SVG frames must always have an nsSVGOuterSVGFrame ancestor!");
|
||||
invalidArea.MoveBy(aFrame->GetContentRect().TopLeft() - aFrame->GetPosition());
|
||||
|
||||
static_cast<nsSVGOuterSVGFrame*>(aFrame)->InvalidateWithFlags(invalidArea,
|
||||
aFlags);
|
||||
|
Loading…
Reference in New Issue
Block a user