Bug 331432. Split nsSVGForeignObjectFrame into a pure SVG frame containing an anonymous block child, to avoid state bit collisions and simplify things. Also fixes configure.in so that foreignObject is really enabled by default in cairo builds. r=tor,sr=bzbarsky

This commit is contained in:
roc+%cs.cmu.edu 2006-06-06 23:13:15 +00:00
Родитель d85b48ecf3
Коммит fe1409e73e
6 изменённых файлов: 65 добавлений и 159 удалений

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

@ -4044,7 +4044,6 @@ MOZ_SINGLE_PROFILE=
MOZ_STATIC_MAIL_BUILD=
MOZ_STORAGE=1
MOZ_SVG=1
MOZ_SVG_FOREIGNOBJECT=$MOZ_ENABLE_CAIRO_GFX
MOZ_TIMELINE=
MOZ_UI_LOCALE=en-US
MOZ_UNIVERSALCHARDET=1
@ -5636,6 +5635,7 @@ if test -n "$MOZ_SVG"; then
AC_DEFINE(MOZ_SVG)
fi
MOZ_SVG_FOREIGNOBJECT=$MOZ_ENABLE_CAIRO_GFX
dnl ========================================================
dnl SVG <foreignObject>
dnl ========================================================

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

@ -7818,32 +7818,43 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsFrameConstructorState& aState,
// If we succeeded in creating a frame then initialize it, process its
// children (if requested), and set the initial child list
if (newFrame != nsnull) {
InitAndRestoreFrame(aState, aContent, geometricParent, nsnull, newFrame);
nsHTMLContainerFrame::CreateViewForFrame(newFrame, aParentFrame, forceView);
rv = aState.AddChild(newFrame, aFrameItems, disp, aContent, aStyleContext,
aParentFrame, isOuterSVGNode, isOuterSVGNode);
if (NS_FAILED(rv)) {
return rv;
}
nsFrameItems childItems;
#ifdef MOZ_SVG_FOREIGNOBJECT
if (aTag == nsSVGAtoms::foreignObject) {
if (aTag == nsSVGAtoms::foreignObject) {
// Resolve pseudo style and create an inner block frame
// XXX this breaks style inheritance
nsRefPtr<nsStyleContext> innerPseudoStyle;
innerPseudoStyle = mPresShell->StyleSet()->
ResolvePseudoStyleFor(aContent,
nsCSSAnonBoxes::mozSVGForeignContent, aStyleContext);
nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, innerPseudoStyle);
if (NS_UNLIKELY(!blockFrame))
return NS_ERROR_OUT_OF_MEMORY;
blockFrame->AddStateBits(NS_BLOCK_SPACE_MGR | NS_BLOCK_MARGIN_ROOT |
NS_FRAME_REFLOW_ROOT);
// Claim to be relatively positioned so that we end up being the
// absolute containing block. Also, push "null" as the float
// containing block so that we get the SPACE_MGR bit set.
// absolute containing block.
nsFrameConstructorSaveState saveState;
aState.PushFloatContainingBlock(nsnull, saveState, PR_FALSE, PR_FALSE);
const nsStyleDisplay* disp = aStyleContext->GetStyleDisplay();
const nsStyleDisplay* disp = innerPseudoStyle->GetStyleDisplay();
rv = ConstructBlock(aState, disp, aContent,
geometricParent, aParentFrame, aStyleContext,
&newFrame, aFrameItems, PR_TRUE);
newFrame, newFrame, innerPseudoStyle,
&blockFrame, childItems, PR_TRUE);
} else
#endif // MOZ_SVG_FOREIGNOBJECT
{
InitAndRestoreFrame(aState, aContent, geometricParent, nsnull, newFrame);
rv = aState.AddChild(newFrame, aFrameItems, disp, aContent, aStyleContext,
aParentFrame, isOuterSVGNode, isOuterSVGNode);
if (NS_FAILED(rv)) {
return rv;
}
nsHTMLContainerFrame::CreateViewForFrame(newFrame, aParentFrame, forceView);
// Process the child content if requested.
nsFrameItems childItems;
if (!newFrame->IsLeaf()) {
if (aTag == nsSVGAtoms::svgSwitch) {
rv = SVGSwitchProcessChildren(aState, aContent, newFrame,
@ -7856,12 +7867,12 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsFrameConstructorState& aState,
}
CreateAnonymousFrames(aTag, aState, aContent, newFrame,
PR_FALSE, childItems);
// Set the frame's initial child list
newFrame->SetInitialChildList(nsnull, childItems.childList);
}
if (!newFrame->IsLeaf())
// Set the frame's initial child list
newFrame->SetInitialChildList(nsnull, childItems.childList);
if (NS_SUCCEEDED(rv) && !newFrame->IsLeaf())
rv = CreateInsertionPointChildren(aState, newFrame, aContent);
return rv;

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

@ -111,3 +111,7 @@ CSS_ANON_BOX(mozMathStretchy, ":-moz-math-stretchy")
CSS_ANON_BOX(mozMathAnonymous, ":-moz-math-anonymous")
CSS_ANON_BOX(mozMathInline, ":-moz-math-inline")
#endif
#ifdef MOZ_SVG
CSS_ANON_BOX(mozSVGForeignContent, ":-moz-svg-foreign-content")
#endif

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

@ -116,8 +116,9 @@
/* Miscellaneous */
*|*::-moz-anonymous-block, *|*::-moz-cell-content {
*|*::-moz-anonymous-block, *|*::-moz-cell-content, *|*::-moz-svg-foreign-content {
display: block !important;
position: static !important;
}
*|*::-moz-scrolled-content, *|*::-moz-scrolled-canvas,

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

@ -83,10 +83,8 @@ NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsSt
nsSVGForeignObjectFrame::nsSVGForeignObjectFrame(nsStyleContext* aContext)
: nsSVGForeignObjectFrameBase(aContext),
mIsDirty(PR_TRUE), mPropagateTransform(PR_TRUE)
mPropagateTransform(PR_TRUE), mIsDirty(PR_TRUE)
{
AddStateBits(NS_BLOCK_SPACE_MGR | NS_BLOCK_MARGIN_ROOT |
NS_FRAME_REFLOW_ROOT);
}
//----------------------------------------------------------------------
@ -101,85 +99,12 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGForeignObjectFrameBase)
//----------------------------------------------------------------------
// nsIFrame methods
NS_IMETHODIMP
nsSVGForeignObjectFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
nsIAtom *
nsSVGForeignObjectFrame::GetType() const
{
nsHTMLReflowState &reflowState =
NS_CONST_CAST(nsHTMLReflowState&, aReflowState);
// We could do this in DoReflow, except that we set
// NS_FRAME_REFLOW_ROOT, so we also need to do it when the pres shell
// calls us directly.
reflowState.mComputedHeight = mRect.height;
reflowState.mComputedWidth = mRect.width;
nsSpaceManager* spaceManager =
new nsSpaceManager(aPresContext->PresShell(), this);
if (!spaceManager) {
NS_ERROR("Could not create space manager");
return nsnull;
}
reflowState.mSpaceManager = spaceManager;
nsresult rv = nsSVGForeignObjectFrameBase::Reflow(aPresContext, aDesiredSize,
aReflowState, aStatus);
reflowState.mSpaceManager = nsnull;
delete spaceManager;
return rv;
return nsLayoutAtoms::svgForeignObjectFrame;
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList)
{
#ifdef DEBUG
printf("**nsSVGForeignObjectFrame::AppendFrames()\n");
#endif
nsresult rv;
rv = nsSVGForeignObjectFrameBase::AppendFrames(aListName, aFrameList);
Update();
return rv;
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::InsertFrames(nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList)
{
#ifdef DEBUG
printf("**nsSVGForeignObjectFrame::InsertFrames()\n");
#endif
nsresult rv;
rv = nsSVGForeignObjectFrameBase::InsertFrames(aListName, aPrevFrame,
aFrameList);
Update();
return rv;
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame)
{
nsresult rv;
rv = nsSVGForeignObjectFrameBase::RemoveFrame(aListName, aOldFrame);
Update();
return rv;
}
// XXX Need to make sure that any of the code examining
// frametypes, particularly code looking at block and area
// also handles foreignObject before we return our own frametype
// nsIAtom *
// nsSVGForeignObjectFrame::GetType() const
// {
// return nsLayoutAtoms::svgForeignObjectFrame;
// }
PRBool
nsSVGForeignObjectFrame::IsFrameOfType(PRUint32 aFlags) const
{
@ -283,34 +208,16 @@ TransformRect(float* aX, float *aY, float* aWidth, float *aHeight,
NS_IMETHODIMP
nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas)
{
nsresult rv = NS_OK;
nsIFrame* kid = GetFirstChild(nsnull);
if (!kid)
return NS_OK;
if (mIsDirty) {
nsCOMPtr<nsISVGRendererRegion> region = DoReflow();
}
nsRect dirtyRect = nsRect(nsPoint(0, 0), GetSize());
nsRect dirtyRect = kid->GetRect();
nsCOMPtr<nsIDOMSVGMatrix> tm = GetTMIncludingOffset();
#if 0 /// XX - broken by PaintSVG API change (bug 330498)
nsCOMPtr<nsIDOMSVGMatrix> inverse;
rv = tm->Inverse(getter_AddRefs(inverse));
float pxPerTwips = GetPxPerTwips();
float twipsPerPx = GetTwipsPerPx();
if (NS_SUCCEEDED(rv)) {
float x = dirtyRectTwips.x*pxPerTwips;
float y = dirtyRectTwips.y*pxPerTwips;
float w = dirtyRectTwips.width*pxPerTwips;
float h = dirtyRectTwips.height*pxPerTwips;
TransformRect(&x, &y, &w, &h, inverse);
nsRect r;
r.x = NSToCoordFloor(x*twipsPerPx);
r.y = NSToCoordFloor(y*twipsPerPx);
r.width = NSToCoordCeil((x + w)*twipsPerPx) - r.x;
r.height = NSToCoordCeil((y + h)*twipsPerPx) - r.y;
dirtyRect.IntersectRect(dirtyRect, r);
}
#endif
if (dirtyRect.IsEmpty())
return NS_OK;
@ -323,8 +230,8 @@ nsSVGForeignObjectFrame::PaintSVG(nsISVGRendererCanvas* canvas)
return NS_ERROR_FAILURE;
}
rv = nsLayoutUtils::PaintFrame(ctx, this, nsRegion(dirtyRect),
NS_RGBA(0,0,0,0));
nsresult rv = nsLayoutUtils::PaintFrame(ctx, kid, nsRegion(dirtyRect),
NS_RGBA(0,0,0,0));
ctx = nsnull;
canvas->UnlockRenderingContext();
@ -555,6 +462,9 @@ nsSVGForeignObjectFrame::DoReflow()
#endif
nsPresContext *presContext = GetPresContext();
nsIFrame* kid = GetFirstChild(nsnull);
if (!kid)
return nsnull;
// remember the area we have to invalidate after this reflow:
nsCOMPtr<nsISVGRendererRegion> area_before = GetCoveredRegion();
@ -581,30 +491,24 @@ nsSVGForeignObjectFrame::DoReflow()
nsSize size(NSFloatPixelsToTwips(width, twipsPerPx),
NSFloatPixelsToTwips(height, twipsPerPx));
// move our frame to (0, 0), set our size to the untransformed
// width and height. Our frame size and position are meaningless
// given the possibility of non-rectilinear transforms; our size
// is only useful for reflowing our content
SetPosition(nsPoint(0, 0));
SetSize(size);
// create a new reflow state, setting our max size to (width,height):
// Make up a potentially reasonable but perhaps too destructive reflow
// reason.
nsReflowReason reason = (GetStateBits() & NS_FRAME_FIRST_REFLOW)
nsReflowReason reason = (kid->GetStateBits() & NS_FRAME_FIRST_REFLOW)
? eReflowReason_Initial
: eReflowReason_StyleChange;
nsHTMLReflowState reflowState(presContext, this, reason,
nsHTMLReflowState reflowState(presContext, kid, reason,
renderingContext, size);
nsHTMLReflowMetrics desiredSize(nsnull);
nsReflowStatus status;
WillReflow(presContext);
Reflow(presContext, desiredSize, reflowState, status);
ReflowChild(kid, presContext, desiredSize, reflowState, 0, 0,
NS_FRAME_NO_MOVE_FRAME, status);
NS_ASSERTION(size.width == desiredSize.width &&
size.height == desiredSize.height, "unexpected size");
DidReflow(presContext, &reflowState, NS_FRAME_REFLOW_FINISHED);
FinishReflowChild(kid, presContext, &reflowState, desiredSize, 0, 0,
NS_FRAME_NO_MOVE_FRAME);
mIsDirty = PR_FALSE;
nsCOMPtr<nsISVGRendererRegion> area_after = GetCoveredRegion();

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

@ -47,7 +47,7 @@
#include "nsIDOMSVGMatrix.h"
#include "nsIDOMSVGLength.h"
typedef nsBlockFrame nsSVGForeignObjectFrameBase;
typedef nsContainerFrame nsSVGForeignObjectFrameBase;
class nsISVGFilterFrame;
@ -68,25 +68,14 @@ private:
NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
public:
// nsIFrame:
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD AppendFrames(nsIAtom* aListName,
nsIFrame* aFrameList);
NS_IMETHOD InsertFrames(nsIAtom* aListName,
nsIFrame* aPrevFrame,
nsIFrame* aFrameList);
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
virtual nsIFrame* GetContentInsertionFrame() {
return GetFirstChild(nsnull)->GetContentInsertionFrame();
}
NS_IMETHOD DidSetStyleContext();
/**
@ -94,10 +83,7 @@ public:
*
* @see nsLayoutAtoms::svgForeignObjectFrame
*/
// XXX Need to make sure that any of the code examining
// frametypes, particularly code looking at block and area
// also handles foreignObject before we return our own frametype
// virtual nsIAtom* GetType() const;
virtual nsIAtom* GetType() const;
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
#ifdef DEBUG