Make percentage width and height work inside of foreignObject by fixing up the way foreignObject initiates the reflow process, and also partly fixing incremental change issues with foreignObject. b=328550 r+sr=roc

git-svn-id: svn://10.0.0.236/trunk@191383 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dbaron%dbaron.org
2006-02-28 11:27:29 +00:00
parent 36efdd6fc8
commit eb12391d73
3 changed files with 68 additions and 79 deletions

View File

@@ -85,6 +85,8 @@ NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent)
nsSVGForeignObjectFrame::nsSVGForeignObjectFrame()
: mIsDirty(PR_TRUE), mPropagateTransform(PR_TRUE), mFilter(nsnull)
{
AddStateBits(NS_BLOCK_SPACE_MGR | NS_BLOCK_MARGIN_ROOT |
NS_FRAME_REFLOW_ROOT);
}
nsSVGForeignObjectFrame::~nsSVGForeignObjectFrame()
@@ -213,39 +215,30 @@ nsSVGForeignObjectFrame::Reflow(nsPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
#ifdef DEBUG
printf("nsSVGForeignObjectFrame(%p)::Reflow\n", this);
#endif
float twipsPerPx = GetTwipsPerPx();
NS_ENSURE_TRUE(mX && mY && mWidth && mHeight, NS_ERROR_FAILURE);
nsHTMLReflowState &reflowState =
NS_CONST_CAST(nsHTMLReflowState&, aReflowState);
float width, height;
mWidth->GetValue(&width);
mHeight->GetValue(&height);
// 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;
// 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));
// create a new reflow state, setting our max size to (width,height):
nsSize availableSpace((nscoord)(width*twipsPerPx), (nscoord)(height*twipsPerPx));
nsHTMLReflowState sizedReflowState(aPresContext,
aReflowState,
this,
availableSpace);
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);
// XXX Not sure the dirty-state should be cleared here. We should
// re-examine how the reflow is driven from nsSVGOuterSVGFrame. I
// think we're missing a call to DidReflow somewhere ?
mState &= ~NS_FRAME_IS_DIRTY;
// leverage our base class' reflow function to do all the work:
return nsSVGForeignObjectFrameBase::Reflow(aPresContext, aDesiredSize,
sizedReflowState, aStatus);
reflowState.mSpaceManager = nsnull;
delete spaceManager;
return rv;
}
NS_IMETHODIMP
@@ -742,24 +735,41 @@ nsSVGForeignObjectFrame::DoReflow()
nsIPresShell* presShell = presContext->PresShell();
NS_ASSERTION(presShell, "null presShell");
presShell->CreateRenderingContext(this,getter_AddRefs(renderingContext));
NS_ENSURE_TRUE(renderingContext, nsnull);
// XXX we always pass this off as an initial reflow. is that a problem?
nsHTMLReflowState reflowState(presContext, this, eReflowReason_Initial,
renderingContext, availableSpace);
float twipsPerPx = GetTwipsPerPx();
NS_ENSURE_TRUE(mX && mY && mWidth && mHeight, nsnull);
nsSpaceManager* spaceManager = new nsSpaceManager(presShell, this);
if (!spaceManager) {
NS_ERROR("Could not create space manager");
return nsnull;
}
reflowState.mSpaceManager = spaceManager;
float width, height;
mWidth->GetValue(&width);
mHeight->GetValue(&height);
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)
? eReflowReason_Initial
: eReflowReason_StyleChange;
nsHTMLReflowState reflowState(presContext, this, reason,
renderingContext, size);
nsHTMLReflowMetrics desiredSize(nsnull);
nsReflowStatus status;
WillReflow(presContext);
Reflow(presContext, desiredSize, reflowState, status);
SetSize(nsSize(desiredSize.width, desiredSize.height));
NS_ASSERTION(size.width == desiredSize.width &&
size.height == desiredSize.height, "unexpected size");
DidReflow(presContext, &reflowState, NS_FRAME_REFLOW_FINISHED);
mIsDirty = PR_FALSE;

View File

@@ -408,45 +408,18 @@ nsSVGOuterSVGFrame::Reflow(nsPresContext* aPresContext,
}
#endif
// check whether this reflow request is targeted at us or a child
// frame (e.g. a foreignObject):
if (aReflowState.reason == eReflowReason_Incremental) {
nsReflowPath::iterator iter = aReflowState.path->FirstChild();
nsReflowPath::iterator end = aReflowState.path->EndChildren();
if (aReflowState.reason == eReflowReason_Incremental &&
!aReflowState.path->mReflowCommand) {
// We're not the target of the incremental reflow, so just bail.
// This means that something happened to one of our descendants
// (excluding those inside svg:foreignObject, since
// nsSVGForeignObjectFrame is a reflow root).
for ( ; iter != end; ++iter) {
// The actual target of this reflow is one of our child
// frames. Since SVG as such doesn't use reflow, this will
// probably be the child of a <foreignObject>. Some HTML|XUL
// content frames target reflow events at themselves when they
// need to be redrawn in response to e.g. a style change. For
// correct visual updating, we must make sure the reflow
// reaches its intended target.
// Since it is an svg frame (probably an nsSVGForeignObjectFrame),
// we might as well pass in our aDesiredSize and aReflowState
// objects - they are ignored by svg frames:
nsSize availSpace(0, 0); // XXXwaterson probably wrong!
nsHTMLReflowState state(aPresContext, aReflowState, *iter, availSpace);
(*iter)->Reflow (aPresContext,
aDesiredSize,
state,
aStatus);
// XXX do we really have to return our metrics although we're
// not affected by the reflow? Is there a way of telling our
// parent that we don't want anything changed?
aDesiredSize.width = mRect.width;
aDesiredSize.height = mRect.height;
aDesiredSize.ascent = aDesiredSize.height;
aDesiredSize.descent = 0;
}
if (! aReflowState.path->mReflowCommand) {
// We're not the target of the incremental reflow, so just bail.
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
// XXXldb If this incremental reflow was the result of a style
// change to something that *contains* a foreignObject, then we're
// dropping the change completely on the floor!
aStatus = NS_FRAME_COMPLETE;
return NS_OK;
}
// SVG CR 20001102: When the SVG content is embedded inline within

View File

@@ -62,3 +62,9 @@ switch {
svg:not(:root), symbol, image, marker, pattern, foreignObject {
overflow: hidden;
}
foreignObject {
margin: 0 ! important;
padding: 0 ! important;
border: none ! important;
}