зеркало из https://github.com/mozilla/gecko-dev.git
Bug 170330. Factor out overflowArea calculations and take into account overflow:hidden. Also improve calculations of clipping for invalidation in the view manager. r+sr=dbaron
This commit is contained in:
Родитель
89d4967bdf
Коммит
a5a3f217d1
|
@ -794,6 +794,13 @@ public:
|
||||||
PRInt32* outFrameContentOffset,
|
PRInt32* outFrameContentOffset,
|
||||||
nsIFrame* *outChildFrame) = 0;
|
nsIFrame* *outChildFrame) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true iff the frame has a view (i.e., GetView() returns non-null)
|
||||||
|
*/
|
||||||
|
PRBool HasView() {
|
||||||
|
return (mState & NS_FRAME_HAS_VIEW) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current frame-state value for this frame. aResult is
|
* Get the current frame-state value for this frame. aResult is
|
||||||
* filled in with the state bits.
|
* filled in with the state bits.
|
||||||
|
|
|
@ -771,21 +771,16 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// Whether or not we're complete hasn't changed
|
// Whether or not we're complete hasn't changed
|
||||||
aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE;
|
aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE;
|
||||||
|
|
||||||
// Factor the absolutely positioned child bounds into the overflow area
|
|
||||||
ComputeCombinedArea(aReflowState, aMetrics);
|
ComputeCombinedArea(aReflowState, aMetrics);
|
||||||
|
|
||||||
|
// Factor the absolutely positioned child bounds into the overflow area
|
||||||
nsRect childBounds;
|
nsRect childBounds;
|
||||||
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
|
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
|
||||||
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
|
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
|
||||||
|
|
||||||
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
|
// Finish computing the overflow area, taking account of outline and
|
||||||
if ((aMetrics.mOverflowArea.x < 0) ||
|
// overflow:hidden etc
|
||||||
(aMetrics.mOverflowArea.y < 0) ||
|
ComputeOverflowArea(aMetrics.mOverflowArea, aMetrics.mOverflowArea);
|
||||||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
|
|
||||||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
} else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -1095,18 +1090,13 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
// Factor the absolutely positioned child bounds into the overflow area
|
// Factor the absolutely positioned child bounds into the overflow area
|
||||||
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
|
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
|
||||||
|
|
||||||
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
|
|
||||||
if ((aMetrics.mOverflowArea.x < 0) ||
|
|
||||||
(aMetrics.mOverflowArea.y < 0) ||
|
|
||||||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
|
|
||||||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
} else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Area of child content has been computed into mOverflowArea
|
||||||
|
// Finish computing the overflow area, taking account of outline and
|
||||||
|
// overflow:hidden etc
|
||||||
|
ComputeOverflowArea(aMetrics.mOverflowArea, aMetrics.mOverflowArea);
|
||||||
|
|
||||||
// Clear the space manager pointer in the block reflow state so we
|
// Clear the space manager pointer in the block reflow state so we
|
||||||
// don't waste time translating the coordinate system back on a dead
|
// don't waste time translating the coordinate system back on a dead
|
||||||
// space manager.
|
// space manager.
|
||||||
|
@ -1169,10 +1159,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_roc
|
|
||||||
printf("*** Metrics width/height on the way out=%d,%d\n", aMetrics.width, aMetrics.height);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -1546,18 +1532,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputeCombinedArea(aReflowState, aMetrics);
|
ComputeCombinedArea(aReflowState, aMetrics);
|
||||||
|
|
||||||
// If the combined area of our children exceeds our bounding box
|
|
||||||
// then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it.
|
|
||||||
if ((aMetrics.mOverflowArea.x < 0) ||
|
|
||||||
(aMetrics.mOverflowArea.y < 0) ||
|
|
||||||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
|
|
||||||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -754,6 +754,55 @@ nsFrame::DisplaySelection(nsIPresContext* aPresContext, PRBool isOkToTurnOn)
|
||||||
return selType;
|
return selType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsFrame::ComputeOverflowArea(nsRect& aOverflowArea,
|
||||||
|
const nsRect& aCombinedChildren)
|
||||||
|
{
|
||||||
|
// the frame's rect in its own coordinate system
|
||||||
|
nsRect r(0, 0, mRect.width, mRect.height);
|
||||||
|
// Make the default combined area: frame U children
|
||||||
|
aOverflowArea.UnionRect(aCombinedChildren, r);
|
||||||
|
// WARNING: aCombinedChildren might be the same rect as aOverflowArea.
|
||||||
|
// It may have been destroyed now. Don't use it below.
|
||||||
|
|
||||||
|
// Don't do the following mildly expensive stuff unless we have a view;
|
||||||
|
// any block frame with overflow:hidden will have a view
|
||||||
|
// (see nsContainerFrame::FrameNeedsView).
|
||||||
|
// HasView() is very cheap; it just checks a bit on mState.
|
||||||
|
if (HasView()) {
|
||||||
|
// The following code is temporarily disabled. We'll turn it on
|
||||||
|
// when proper support for 'outline' lands. Note that it assumes
|
||||||
|
// any frame with 'outline' has a view. --- roc
|
||||||
|
#if 0
|
||||||
|
// Add in the outline width, which overflows our border area
|
||||||
|
const nsStyleOutline* outline;
|
||||||
|
::GetStyleData(mStyleContext, &outline);
|
||||||
|
|
||||||
|
nscoord width;
|
||||||
|
outline->GetOutlineWidth(width);
|
||||||
|
r.Inflate(width, width);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// overflow:hidden doesn't need to take account of the child area
|
||||||
|
const nsStyleDisplay* display;
|
||||||
|
::GetStyleData(mStyleContext, &display);
|
||||||
|
if (NS_STYLE_OVERFLOW_HIDDEN == display->mOverflow
|
||||||
|
&& (display->IsBlockLevel() || display->IsFloating())) {
|
||||||
|
aOverflowArea = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set state bit to indicate whether there is any overflow
|
||||||
|
if (aOverflowArea.x < 0
|
||||||
|
|| aOverflowArea.y < 0
|
||||||
|
|| aOverflowArea.XMost() > mRect.width
|
||||||
|
|| aOverflowArea.YMost() > mRect.height) {
|
||||||
|
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
||||||
|
} else {
|
||||||
|
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsFrame::SetOverflowClipRect(nsIRenderingContext& aRenderingContext)
|
nsFrame::SetOverflowClipRect(nsIRenderingContext& aRenderingContext)
|
||||||
{
|
{
|
||||||
|
|
|
@ -348,6 +348,11 @@ public:
|
||||||
const nsRect& aDamageRect,
|
const nsRect& aDamageRect,
|
||||||
PRBool aImmediate = PR_FALSE) const;
|
PRBool aImmediate = PR_FALSE) const;
|
||||||
|
|
||||||
|
// Helper function to compute the overflow area for a frame,
|
||||||
|
// taking into account overflow:hidden and any outline present.
|
||||||
|
// This sets the frame state bit FRAME_OUTSIDE_CHILDREN if necessary.
|
||||||
|
void ComputeOverflowArea(nsRect& aOverflowArea, const nsRect& aCombinedChildren);
|
||||||
|
|
||||||
// Helper function to return the index in parent of the frame's content
|
// Helper function to return the index in parent of the frame's content
|
||||||
// object. Returns -1 on error or if the frame doesn't have a content object
|
// object. Returns -1 on error or if the frame doesn't have a content object
|
||||||
static PRInt32 ContentIndexInContainer(const nsIFrame* aFrame);
|
static PRInt32 ContentIndexInContainer(const nsIFrame* aFrame);
|
||||||
|
|
|
@ -794,6 +794,13 @@ public:
|
||||||
PRInt32* outFrameContentOffset,
|
PRInt32* outFrameContentOffset,
|
||||||
nsIFrame* *outChildFrame) = 0;
|
nsIFrame* *outChildFrame) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true iff the frame has a view (i.e., GetView() returns non-null)
|
||||||
|
*/
|
||||||
|
PRBool HasView() {
|
||||||
|
return (mState & NS_FRAME_HAS_VIEW) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current frame-state value for this frame. aResult is
|
* Get the current frame-state value for this frame. aResult is
|
||||||
* filled in with the state bits.
|
* filled in with the state bits.
|
||||||
|
|
|
@ -1311,16 +1311,8 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
|
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
|
||||||
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds);
|
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds);
|
||||||
|
|
||||||
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
|
|
||||||
if ((aDesiredSize.mOverflowArea.x < 0) ||
|
|
||||||
(aDesiredSize.mOverflowArea.y < 0) ||
|
|
||||||
(aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) ||
|
|
||||||
(aDesiredSize.mOverflowArea.YMost() > aDesiredSize.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
} else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
// Don't update the overflow area state here. It's done by line layout.
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1356,16 +1348,8 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// Factor the absolutely positioned child bounds into the overflow area
|
// Factor the absolutely positioned child bounds into the overflow area
|
||||||
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds);
|
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds);
|
||||||
|
|
||||||
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
|
|
||||||
if ((aDesiredSize.mOverflowArea.x < 0) ||
|
|
||||||
(aDesiredSize.mOverflowArea.y < 0) ||
|
|
||||||
(aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) ||
|
|
||||||
(aDesiredSize.mOverflowArea.YMost() > aDesiredSize.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
} else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
// Don't update the overflow area state here. It's done by line layout.
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -1258,16 +1258,11 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
nsIView* view;
|
nsIView* view;
|
||||||
aFrame->GetView(mPresContext, &view);
|
aFrame->GetView(mPresContext, &view);
|
||||||
if (view) {
|
if (view) {
|
||||||
nsIViewManager *vm;
|
nsCOMPtr<nsIViewManager> vm;
|
||||||
view->GetViewManager(vm);
|
view->GetViewManager(*getter_AddRefs(vm));
|
||||||
|
|
||||||
#if 0 // XXX This is the correct code. We'll turn it on later to mitigate risk.
|
|
||||||
vm->ResizeView(view, pfd->mCombinedArea);
|
vm->ResizeView(view, pfd->mCombinedArea);
|
||||||
#else // imitate the old, wrong code
|
nsContainerFrame::SyncFrameViewAfterSizeChange(mPresContext, pfd->mFrame, nsnull, view);
|
||||||
nsRect r(0, 0, metrics.width, metrics.height);
|
|
||||||
vm->ResizeView(view, r);
|
|
||||||
#endif
|
|
||||||
NS_RELEASE(vm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the frame that we're done reflowing it
|
// Tell the frame that we're done reflowing it
|
||||||
|
@ -3323,20 +3318,26 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we just computed a spans combined area, we need to update its
|
// If we just computed a spans combined area, we need to update its
|
||||||
// NS_FRAME_OUTSIDE_CHILDREN bit..
|
// NS_FRAME_OUTSIDE_CHILDREN bit. We also may need to take into account
|
||||||
|
// an outline.
|
||||||
if (nsnull != psd->mFrame) {
|
if (nsnull != psd->mFrame) {
|
||||||
pfd = psd->mFrame;
|
pfd = psd->mFrame;
|
||||||
nsIFrame* frame = pfd->mFrame;
|
nsIFrame* frame = pfd->mFrame;
|
||||||
nsFrameState oldState;
|
|
||||||
frame->GetFrameState(&oldState);
|
// We're conservative here; the combined area for this span/frame
|
||||||
nsFrameState newState = oldState & ~NS_FRAME_OUTSIDE_CHILDREN;
|
// is the union of the area that the frame computed during reflow
|
||||||
if ((minX < 0) || (minY < 0) ||
|
// and the area that we computed for it here in RelativePositionFrames.
|
||||||
(maxX > pfd->mBounds.width) || (maxY > pfd->mBounds.height)) {
|
// We do this because relatively positioned frames that are also spans
|
||||||
newState |= NS_FRAME_OUTSIDE_CHILDREN;
|
// have two contributors to the overflow area: overflowing inline children
|
||||||
}
|
// and overflowing absolute children.
|
||||||
if (newState != oldState) {
|
// This could be larger than necessary if inline alignment caused an inline child
|
||||||
frame->SetFrameState(newState);
|
// to overflow less, because its old overflow would still be counted in
|
||||||
}
|
// pfd->mCombinedArea.
|
||||||
|
// But in practice it's OK to have an overflow area that's larger than necessary.
|
||||||
|
// (Although if it happens too often it could become a paint performance issue).
|
||||||
|
nsRect children;
|
||||||
|
children.UnionRect(pfd->mCombinedArea, aCombinedArea);
|
||||||
|
NS_STATIC_CAST(nsFrame*, frame)->ComputeOverflowArea(aCombinedArea, children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -771,21 +771,16 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// Whether or not we're complete hasn't changed
|
// Whether or not we're complete hasn't changed
|
||||||
aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE;
|
aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE;
|
||||||
|
|
||||||
// Factor the absolutely positioned child bounds into the overflow area
|
|
||||||
ComputeCombinedArea(aReflowState, aMetrics);
|
ComputeCombinedArea(aReflowState, aMetrics);
|
||||||
|
|
||||||
|
// Factor the absolutely positioned child bounds into the overflow area
|
||||||
nsRect childBounds;
|
nsRect childBounds;
|
||||||
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
|
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
|
||||||
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
|
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
|
||||||
|
|
||||||
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
|
// Finish computing the overflow area, taking account of outline and
|
||||||
if ((aMetrics.mOverflowArea.x < 0) ||
|
// overflow:hidden etc
|
||||||
(aMetrics.mOverflowArea.y < 0) ||
|
ComputeOverflowArea(aMetrics.mOverflowArea, aMetrics.mOverflowArea);
|
||||||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
|
|
||||||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
} else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -1095,18 +1090,13 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
// Factor the absolutely positioned child bounds into the overflow area
|
// Factor the absolutely positioned child bounds into the overflow area
|
||||||
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
|
aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);
|
||||||
|
|
||||||
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
|
|
||||||
if ((aMetrics.mOverflowArea.x < 0) ||
|
|
||||||
(aMetrics.mOverflowArea.y < 0) ||
|
|
||||||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
|
|
||||||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
} else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Area of child content has been computed into mOverflowArea
|
||||||
|
// Finish computing the overflow area, taking account of outline and
|
||||||
|
// overflow:hidden etc
|
||||||
|
ComputeOverflowArea(aMetrics.mOverflowArea, aMetrics.mOverflowArea);
|
||||||
|
|
||||||
// Clear the space manager pointer in the block reflow state so we
|
// Clear the space manager pointer in the block reflow state so we
|
||||||
// don't waste time translating the coordinate system back on a dead
|
// don't waste time translating the coordinate system back on a dead
|
||||||
// space manager.
|
// space manager.
|
||||||
|
@ -1169,10 +1159,6 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_roc
|
|
||||||
printf("*** Metrics width/height on the way out=%d,%d\n", aMetrics.width, aMetrics.height);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -1546,18 +1532,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputeCombinedArea(aReflowState, aMetrics);
|
ComputeCombinedArea(aReflowState, aMetrics);
|
||||||
|
|
||||||
// If the combined area of our children exceeds our bounding box
|
|
||||||
// then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear it.
|
|
||||||
if ((aMetrics.mOverflowArea.x < 0) ||
|
|
||||||
(aMetrics.mOverflowArea.y < 0) ||
|
|
||||||
(aMetrics.mOverflowArea.XMost() > aMetrics.width) ||
|
|
||||||
(aMetrics.mOverflowArea.YMost() > aMetrics.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -754,6 +754,55 @@ nsFrame::DisplaySelection(nsIPresContext* aPresContext, PRBool isOkToTurnOn)
|
||||||
return selType;
|
return selType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsFrame::ComputeOverflowArea(nsRect& aOverflowArea,
|
||||||
|
const nsRect& aCombinedChildren)
|
||||||
|
{
|
||||||
|
// the frame's rect in its own coordinate system
|
||||||
|
nsRect r(0, 0, mRect.width, mRect.height);
|
||||||
|
// Make the default combined area: frame U children
|
||||||
|
aOverflowArea.UnionRect(aCombinedChildren, r);
|
||||||
|
// WARNING: aCombinedChildren might be the same rect as aOverflowArea.
|
||||||
|
// It may have been destroyed now. Don't use it below.
|
||||||
|
|
||||||
|
// Don't do the following mildly expensive stuff unless we have a view;
|
||||||
|
// any block frame with overflow:hidden will have a view
|
||||||
|
// (see nsContainerFrame::FrameNeedsView).
|
||||||
|
// HasView() is very cheap; it just checks a bit on mState.
|
||||||
|
if (HasView()) {
|
||||||
|
// The following code is temporarily disabled. We'll turn it on
|
||||||
|
// when proper support for 'outline' lands. Note that it assumes
|
||||||
|
// any frame with 'outline' has a view. --- roc
|
||||||
|
#if 0
|
||||||
|
// Add in the outline width, which overflows our border area
|
||||||
|
const nsStyleOutline* outline;
|
||||||
|
::GetStyleData(mStyleContext, &outline);
|
||||||
|
|
||||||
|
nscoord width;
|
||||||
|
outline->GetOutlineWidth(width);
|
||||||
|
r.Inflate(width, width);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// overflow:hidden doesn't need to take account of the child area
|
||||||
|
const nsStyleDisplay* display;
|
||||||
|
::GetStyleData(mStyleContext, &display);
|
||||||
|
if (NS_STYLE_OVERFLOW_HIDDEN == display->mOverflow
|
||||||
|
&& (display->IsBlockLevel() || display->IsFloating())) {
|
||||||
|
aOverflowArea = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set state bit to indicate whether there is any overflow
|
||||||
|
if (aOverflowArea.x < 0
|
||||||
|
|| aOverflowArea.y < 0
|
||||||
|
|| aOverflowArea.XMost() > mRect.width
|
||||||
|
|| aOverflowArea.YMost() > mRect.height) {
|
||||||
|
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
||||||
|
} else {
|
||||||
|
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsFrame::SetOverflowClipRect(nsIRenderingContext& aRenderingContext)
|
nsFrame::SetOverflowClipRect(nsIRenderingContext& aRenderingContext)
|
||||||
{
|
{
|
||||||
|
|
|
@ -348,6 +348,11 @@ public:
|
||||||
const nsRect& aDamageRect,
|
const nsRect& aDamageRect,
|
||||||
PRBool aImmediate = PR_FALSE) const;
|
PRBool aImmediate = PR_FALSE) const;
|
||||||
|
|
||||||
|
// Helper function to compute the overflow area for a frame,
|
||||||
|
// taking into account overflow:hidden and any outline present.
|
||||||
|
// This sets the frame state bit FRAME_OUTSIDE_CHILDREN if necessary.
|
||||||
|
void ComputeOverflowArea(nsRect& aOverflowArea, const nsRect& aCombinedChildren);
|
||||||
|
|
||||||
// Helper function to return the index in parent of the frame's content
|
// Helper function to return the index in parent of the frame's content
|
||||||
// object. Returns -1 on error or if the frame doesn't have a content object
|
// object. Returns -1 on error or if the frame doesn't have a content object
|
||||||
static PRInt32 ContentIndexInContainer(const nsIFrame* aFrame);
|
static PRInt32 ContentIndexInContainer(const nsIFrame* aFrame);
|
||||||
|
|
|
@ -1311,16 +1311,8 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
|
mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);
|
||||||
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds);
|
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds);
|
||||||
|
|
||||||
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
|
|
||||||
if ((aDesiredSize.mOverflowArea.x < 0) ||
|
|
||||||
(aDesiredSize.mOverflowArea.y < 0) ||
|
|
||||||
(aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) ||
|
|
||||||
(aDesiredSize.mOverflowArea.YMost() > aDesiredSize.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
} else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
// Don't update the overflow area state here. It's done by line layout.
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1356,16 +1348,8 @@ nsPositionedInlineFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// Factor the absolutely positioned child bounds into the overflow area
|
// Factor the absolutely positioned child bounds into the overflow area
|
||||||
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds);
|
aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, childBounds);
|
||||||
|
|
||||||
// Make sure the NS_FRAME_OUTSIDE_CHILDREN flag is set correctly
|
|
||||||
if ((aDesiredSize.mOverflowArea.x < 0) ||
|
|
||||||
(aDesiredSize.mOverflowArea.y < 0) ||
|
|
||||||
(aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) ||
|
|
||||||
(aDesiredSize.mOverflowArea.YMost() > aDesiredSize.height)) {
|
|
||||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
} else {
|
|
||||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
// Don't update the overflow area state here. It's done by line layout.
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -1258,16 +1258,11 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
nsIView* view;
|
nsIView* view;
|
||||||
aFrame->GetView(mPresContext, &view);
|
aFrame->GetView(mPresContext, &view);
|
||||||
if (view) {
|
if (view) {
|
||||||
nsIViewManager *vm;
|
nsCOMPtr<nsIViewManager> vm;
|
||||||
view->GetViewManager(vm);
|
view->GetViewManager(*getter_AddRefs(vm));
|
||||||
|
|
||||||
#if 0 // XXX This is the correct code. We'll turn it on later to mitigate risk.
|
|
||||||
vm->ResizeView(view, pfd->mCombinedArea);
|
vm->ResizeView(view, pfd->mCombinedArea);
|
||||||
#else // imitate the old, wrong code
|
nsContainerFrame::SyncFrameViewAfterSizeChange(mPresContext, pfd->mFrame, nsnull, view);
|
||||||
nsRect r(0, 0, metrics.width, metrics.height);
|
|
||||||
vm->ResizeView(view, r);
|
|
||||||
#endif
|
|
||||||
NS_RELEASE(vm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the frame that we're done reflowing it
|
// Tell the frame that we're done reflowing it
|
||||||
|
@ -3323,20 +3318,26 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we just computed a spans combined area, we need to update its
|
// If we just computed a spans combined area, we need to update its
|
||||||
// NS_FRAME_OUTSIDE_CHILDREN bit..
|
// NS_FRAME_OUTSIDE_CHILDREN bit. We also may need to take into account
|
||||||
|
// an outline.
|
||||||
if (nsnull != psd->mFrame) {
|
if (nsnull != psd->mFrame) {
|
||||||
pfd = psd->mFrame;
|
pfd = psd->mFrame;
|
||||||
nsIFrame* frame = pfd->mFrame;
|
nsIFrame* frame = pfd->mFrame;
|
||||||
nsFrameState oldState;
|
|
||||||
frame->GetFrameState(&oldState);
|
// We're conservative here; the combined area for this span/frame
|
||||||
nsFrameState newState = oldState & ~NS_FRAME_OUTSIDE_CHILDREN;
|
// is the union of the area that the frame computed during reflow
|
||||||
if ((minX < 0) || (minY < 0) ||
|
// and the area that we computed for it here in RelativePositionFrames.
|
||||||
(maxX > pfd->mBounds.width) || (maxY > pfd->mBounds.height)) {
|
// We do this because relatively positioned frames that are also spans
|
||||||
newState |= NS_FRAME_OUTSIDE_CHILDREN;
|
// have two contributors to the overflow area: overflowing inline children
|
||||||
}
|
// and overflowing absolute children.
|
||||||
if (newState != oldState) {
|
// This could be larger than necessary if inline alignment caused an inline child
|
||||||
frame->SetFrameState(newState);
|
// to overflow less, because its old overflow would still be counted in
|
||||||
}
|
// pfd->mCombinedArea.
|
||||||
|
// But in practice it's OK to have an overflow area that's larger than necessary.
|
||||||
|
// (Although if it happens too often it could become a paint performance issue).
|
||||||
|
nsRect children;
|
||||||
|
children.UnionRect(pfd->mCombinedArea, aCombinedArea);
|
||||||
|
NS_STATIC_CAST(nsFrame*, frame)->ComputeOverflowArea(aCombinedArea, children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -547,6 +547,9 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//update view as if a child view was being invalidated,
|
||||||
|
//so the view should apply its 'child clip'
|
||||||
|
#define NS_VMREFRESH_FORCHILD 0x0001
|
||||||
//update view now?
|
//update view now?
|
||||||
#define NS_VMREFRESH_IMMEDIATE 0x0002
|
#define NS_VMREFRESH_IMMEDIATE 0x0002
|
||||||
//prevent "sync painting"
|
//prevent "sync painting"
|
||||||
|
|
|
@ -1629,12 +1629,18 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRU
|
||||||
}
|
}
|
||||||
view->ConvertFromParentCoords(&clippedRect.x, &clippedRect.y);
|
view->ConvertFromParentCoords(&clippedRect.x, &clippedRect.y);
|
||||||
|
|
||||||
|
if ((aUpdateFlags & NS_VMREFRESH_FORCHILD) != 0 && view->GetClipChildren()) {
|
||||||
|
nsRect childClipRect;
|
||||||
|
view->GetChildClip(childClipRect);
|
||||||
|
if (!clippedRect.IntersectRect(clippedRect, childClipRect)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsRect damagedRect;
|
nsRect damagedRect;
|
||||||
damagedRect.x = aRect.x;
|
if (!damagedRect.IntersectRect(aRect, clippedRect)) {
|
||||||
damagedRect.y = aRect.y;
|
return NS_OK;
|
||||||
damagedRect.width = aRect.width;
|
}
|
||||||
damagedRect.height = aRect.height;
|
|
||||||
damagedRect.IntersectRect(aRect, clippedRect);
|
|
||||||
|
|
||||||
// If the rectangle is not visible then abort
|
// If the rectangle is not visible then abort
|
||||||
// without invalidating. This is a performance
|
// without invalidating. This is a performance
|
||||||
|
@ -2500,10 +2506,10 @@ NS_IMETHODIMP nsViewManager::MoveViewTo(nsIView *aView, nscoord aX, nscoord aY)
|
||||||
view->GetVisibility(visibility);
|
view->GetVisibility(visibility);
|
||||||
if (visibility != nsViewVisibility_kHide) {
|
if (visibility != nsViewVisibility_kHide) {
|
||||||
nsView* parentView = view->GetParent();
|
nsView* parentView = view->GetParent();
|
||||||
UpdateView(parentView, oldArea, NS_VMREFRESH_NO_SYNC);
|
UpdateView(parentView, oldArea, NS_VMREFRESH_NO_SYNC | NS_VMREFRESH_FORCHILD);
|
||||||
nsRect newArea;
|
nsRect newArea;
|
||||||
view->GetBounds(newArea);
|
view->GetBounds(newArea);
|
||||||
UpdateView(parentView, newArea, NS_VMREFRESH_NO_SYNC);
|
UpdateView(parentView, newArea, NS_VMREFRESH_NO_SYNC | NS_VMREFRESH_FORCHILD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -2564,7 +2570,7 @@ NS_IMETHODIMP nsViewManager::ResizeView(nsIView *aView, const nsRect &aRect, PRB
|
||||||
|
|
||||||
UpdateView(view, aRect, NS_VMREFRESH_NO_SYNC);
|
UpdateView(view, aRect, NS_VMREFRESH_NO_SYNC);
|
||||||
view->ConvertToParentCoords(&oldDimensions.x, &oldDimensions.y);
|
view->ConvertToParentCoords(&oldDimensions.x, &oldDimensions.y);
|
||||||
UpdateView(parentView, oldDimensions, NS_VMREFRESH_NO_SYNC);
|
UpdateView(parentView, oldDimensions, NS_VMREFRESH_NO_SYNC | NS_VMREFRESH_FORCHILD);
|
||||||
} else {
|
} else {
|
||||||
view->SetDimensions(aRect, PR_FALSE);
|
view->SetDimensions(aRect, PR_FALSE);
|
||||||
|
|
||||||
|
@ -2572,7 +2578,7 @@ NS_IMETHODIMP nsViewManager::ResizeView(nsIView *aView, const nsRect &aRect, PRB
|
||||||
nsRect r = aRect;
|
nsRect r = aRect;
|
||||||
view->ConvertToParentCoords(&r.x, &r.y);
|
view->ConvertToParentCoords(&r.x, &r.y);
|
||||||
view->ConvertToParentCoords(&oldDimensions.x, &oldDimensions.y);
|
view->ConvertToParentCoords(&oldDimensions.x, &oldDimensions.y);
|
||||||
InvalidateRectDifference(parentView, oldDimensions, r, NS_VMREFRESH_NO_SYNC);
|
InvalidateRectDifference(parentView, oldDimensions, r, NS_VMREFRESH_NO_SYNC | NS_VMREFRESH_FORCHILD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2650,7 +2656,8 @@ NS_IMETHODIMP nsViewManager::SetViewChildClipRegion(nsIView *aView, const nsRegi
|
||||||
if (parent != nsnull) {
|
if (parent != nsnull) {
|
||||||
view->ConvertToParentCoords(&oldClipRect.x, &oldClipRect.y);
|
view->ConvertToParentCoords(&oldClipRect.x, &oldClipRect.y);
|
||||||
view->ConvertToParentCoords(&newClipRect.x, &newClipRect.y);
|
view->ConvertToParentCoords(&newClipRect.x, &newClipRect.y);
|
||||||
InvalidateRectDifference(parent, oldClipRect, newClipRect, NS_VMREFRESH_NO_SYNC);
|
InvalidateRectDifference(parent, oldClipRect, newClipRect,
|
||||||
|
NS_VMREFRESH_NO_SYNC | NS_VMREFRESH_FORCHILD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2887,7 +2894,7 @@ NS_IMETHODIMP nsViewManager::SetViewVisibility(nsIView *aView, nsViewVisibility
|
||||||
if (parentView) {
|
if (parentView) {
|
||||||
nsRect bounds;
|
nsRect bounds;
|
||||||
view->GetBounds(bounds);
|
view->GetBounds(bounds);
|
||||||
UpdateView(parentView, bounds, NS_VMREFRESH_NO_SYNC);
|
UpdateView(parentView, bounds, NS_VMREFRESH_NO_SYNC | NS_VMREFRESH_FORCHILD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче