Bug 524925 - Recompute overflow without reflowing for transforms. part=1/6 r=dbaron

Add an extra change hint, UpdateOverflow, that can be used to specify that
a frame's overflow areas may have changed and that they need to be recalculated.
When a transform on a frame changes, instead of marking it for reflow, set this
hint instead.

There is an added virtual function on nsIFrame, UpdateOverflow, which is called
recursively on a frame when the corresponding hint is set, to allow it to
update its overflow areas.
This commit is contained in:
Benjamin Stover 2011-06-15 14:03:49 -07:00
Родитель c8a56c9ea5
Коммит dc9cd57308
32 изменённых файлов: 295 добавлений и 98 удалений

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

@ -8019,6 +8019,30 @@ nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
ApplyRenderingChangeToTree(presContext, frame, hint);
didInvalidate = true;
}
if (hint & nsChangeHint_UpdateOverflow) {
nsOverflowAreas overflowAreas;
nsOverflowAreas* pre = static_cast<nsOverflowAreas*>
(frame->Properties().Get(frame->PreTransformOverflowAreasProperty()));
if (pre) {
// FinishAndStoreOverflow will change the overflow areas passed in,
// so make a copy.
overflowAreas = *pre;
} else {
// There is no transform yet on this frame, so we can just use its
// current overflow areas.
overflowAreas = frame->GetOverflowAreas();
}
frame->FinishAndStoreOverflow(overflowAreas, frame->GetSize());
// Ancestors' oveflow areas may be affected.
for (nsIFrame* ancestor = frame->GetParent(); ancestor;
ancestor = ancestor->GetParent()) {
if (!ancestor->UpdateOverflow()) {
break;
}
}
}
if (hint & nsChangeHint_UpdateCursor) {
mPresShell->SynthesizeMouseMove(false);
}

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

@ -91,7 +91,11 @@ enum nsChangeHint {
// change requires frame change (e.g., display:).
// This subsumes all the above.
nsChangeHint_ReconstructFrame = 0x400
nsChangeHint_ReconstructFrame = 0x400,
// The frame's effect on its ancestors' overflow areas has changed,
// either through a change in its transform or a change in its position.
nsChangeHint_UpdateOverflow = 0x800
};
// Redefine these operators to return nothing. This will catch any use

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

@ -163,6 +163,27 @@ nsLayoutUtils::Are3DTransformsEnabled()
return s3DTransformsEnabled;
}
void
nsLayoutUtils::UnionChildOverflow(nsIFrame* aFrame,
nsOverflowAreas& aOverflowAreas)
{
// Iterate over all children except pop-ups
for (nsIFrame::ChildListIterator childLists(aFrame);
!childLists.IsDone(); childLists.Next()) {
if (childLists.CurrentID() == nsIFrame::kPopupList ||
childLists.CurrentID() == nsIFrame::kSelectPopupList)
continue;
nsFrameList children = childLists.CurrentList();
for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) {
nsIFrame* child = e.get();
nsOverflowAreas childOverflow =
child->GetOverflowAreas() + child->GetPosition();
aOverflowAreas.UnionWith(childOverflow);
}
}
}
static void DestroyViewID(void* aObject, nsIAtom* aPropertyName,
void* aPropertyValue, void* aData)
{

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

@ -1475,6 +1475,13 @@ public:
*/
static bool Are3DTransformsEnabled();
/**
* Unions the overflow areas of all non-popup children of aFrame with
* aOverflowAreas.
*/
static void UnionChildOverflow(nsIFrame* aFrame,
nsOverflowAreas& aOverflowAreas);
/**
* Return whether this is a frame whose width is used when computing
* the font size inflation of its descendants.

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

@ -654,7 +654,7 @@ nsTextControlFrame::GetBoxAscent(nsBoxLayoutState& aState)
}
bool
nsTextControlFrame::IsCollapsed(nsBoxLayoutState& aBoxLayoutState)
nsTextControlFrame::IsCollapsed()
{
// We're never collapsed in the box sense.
return false;

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

@ -95,7 +95,7 @@ public:
virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState);
virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState);
virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState);
virtual bool IsCollapsed(nsBoxLayoutState& aBoxLayoutState);
virtual bool IsCollapsed();
DECL_DO_GLOBAL_REFLOW_COUNT_DSP(nsTextControlFrame, nsStackFrame)

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

@ -921,9 +921,9 @@ CalculateContainingBlockSizeForAbsolutes(const nsHTMLReflowState& aReflowState,
}
static inline bool IsClippingChildren(nsIFrame* aFrame,
const nsHTMLReflowState& aReflowState)
const nsStyleDisplay* display)
{
return aReflowState.mStyleDisplay->mOverflowX == NS_STYLE_OVERFLOW_CLIP ||
return display->mOverflowX == NS_STYLE_OVERFLOW_CLIP ||
nsFrame::ApplyPaginatedOverflowClipping(aFrame);
}
@ -958,7 +958,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// make sure our kids fit too.
if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE &&
aReflowState.ComputedHeight() != NS_AUTOHEIGHT &&
IsClippingChildren(this, aReflowState)) {
IsClippingChildren(this, aReflowState.mStyleDisplay)) {
nsMargin heightExtras = aReflowState.mComputedBorderPadding;
if (GetSkipSides() & NS_SIDE_TOP) {
heightExtras.top = 0;
@ -1122,7 +1122,9 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// Compute our final size
nscoord bottomEdgeOfChildren;
ComputeFinalSize(*reflowState, state, aMetrics, &bottomEdgeOfChildren);
ComputeOverflowAreas(*reflowState, aMetrics, bottomEdgeOfChildren);
nsRect areaBounds = nsRect(0, 0, aMetrics.width, aMetrics.height);
ComputeOverflowAreas(areaBounds, reflowState->mStyleDisplay,
bottomEdgeOfChildren, aMetrics.mOverflowAreas);
// Factor overflow container child bounds into the overflow area
aMetrics.mOverflowAreas.UnionWith(ocBounds);
// Factor pushed float child bounds into the overflow area
@ -1452,17 +1454,16 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
}
void
nsBlockFrame::ComputeOverflowAreas(const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aMetrics,
nscoord aBottomEdgeOfChildren)
nsBlockFrame::ComputeOverflowAreas(const nsRect& aBounds,
const nsStyleDisplay* aDisplay,
nscoord aBottomEdgeOfChildren,
nsOverflowAreas& aOverflowAreas)
{
// Compute the overflow areas of our children
// XXX_perf: This can be done incrementally. It is currently one of
// the things that makes incremental reflow O(N^2).
nsRect bounds(0, 0, aMetrics.width, aMetrics.height);
nsOverflowAreas areas(bounds, bounds);
if (!IsClippingChildren(this, aReflowState)) {
nsOverflowAreas areas(aBounds, aBounds);
if (!IsClippingChildren(this, aDisplay)) {
for (line_iterator line = begin_lines(), line_end = end_lines();
line != line_end;
++line) {
@ -1494,7 +1495,31 @@ nsBlockFrame::ComputeOverflowAreas(const nsHTMLReflowState& aReflowState,
printf(": ca=%d,%d,%d,%d\n", area.x, area.y, area.width, area.height);
#endif
aMetrics.mOverflowAreas = areas;
aOverflowAreas = areas;
}
bool
nsBlockFrame::UpdateOverflow()
{
// We need to update the overflow areas of lines manually, as they
// get cached and re-used otherwise. Lines aren't exposed as normal
// frame children, so calling UnionChildOverflow alone will end up
// using the old cached values.
for (line_iterator line = begin_lines(), line_end = end_lines();
line != line_end;
++line) {
nsOverflowAreas lineAreas;
PRInt32 n = line->GetChildCount();
for (nsIFrame* lineFrame = line->mFirstChild;
n > 0; lineFrame = lineFrame->GetNextSibling(), --n) {
ConsiderChildOverflow(lineAreas, lineFrame);
}
line->SetOverflowAreas(lineAreas);
}
return nsBlockFrameSuper::UpdateOverflow();
}
nsresult

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

@ -384,9 +384,10 @@ protected:
nsHTMLReflowMetrics& aMetrics,
nscoord* aBottomEdgeOfChildren);
void ComputeOverflowAreas(const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aMetrics,
nscoord aBottomEdgeOfChildren);
void ComputeOverflowAreas(const nsRect& aBounds,
const nsStyleDisplay* aDisplay,
nscoord aBottomEdgeOfChildren,
nsOverflowAreas& aOverflowAreas);
/** add the frames in aFrameList to this block after aPrevSibling
* this block thinks in terms of lines, but the frame construction code
@ -435,6 +436,8 @@ public:
nsBlockFrame* aOldParent, bool aFromOverflow,
bool aReparentSiblings);
virtual bool UpdateOverflow();
/** Load all of aFrame's floats into the float manager iff aFrame is not a
* block formatting context. Handles all necessary float manager translations;
* assumes float manager is in aFrame's parent's coord system.

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

@ -4849,14 +4849,44 @@ nsRect
nsIFrame::GetVisualOverflowRectRelativeToSelf() const
{
if (IsTransformed()) {
nsRect* preTransformBBox = static_cast<nsRect*>
(Properties().Get(PreTransformBBoxProperty()));
if (preTransformBBox)
return *preTransformBBox;
nsOverflowAreas* preTransformOverflows = static_cast<nsOverflowAreas*>
(Properties().Get(PreTransformOverflowAreasProperty()));
if (preTransformOverflows)
return preTransformOverflows->VisualOverflow();
}
return GetVisualOverflowRect();
}
/* virtual */ bool
nsFrame::UpdateOverflow()
{
nsRect rect(nsPoint(0, 0), GetSize());
nsOverflowAreas overflowAreas(rect, rect);
bool isBox = IsBoxFrame() || IsBoxWrapped();
if (!isBox || (!IsCollapsed() && !DoesClipChildren())) {
nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
}
if (FinishAndStoreOverflow(overflowAreas, GetSize())) {
nsIView* view = GetView();
if (view) {
PRUint32 flags = 0;
GetLayoutFlags(flags);
if ((flags & NS_FRAME_NO_SIZE_VIEW) == 0) {
// Make sure the frame's view is properly sized.
nsIViewManager* vm = view->GetViewManager();
vm->ResizeView(view, overflowAreas.VisualOverflow(), true);
}
}
return true;
}
return false;
}
void
nsFrame::CheckInvalidateSizeChange(nsHTMLReflowMetrics& aNewDesiredSize)
{
@ -6584,6 +6614,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
(disp->mOverflowX == NS_STYLE_OVERFLOW_CLIP),
"If one overflow is clip, the other should be too");
if (disp->mOverflowX == NS_STYLE_OVERFLOW_CLIP ||
disp->IsTableClip() ||
nsFrame::ApplyPaginatedOverflowClipping(this)) {
// The contents are actually clipped to the padding area
aOverflowAreas.SetAllTo(bounds);
@ -6648,8 +6679,8 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
/* If we're transformed, transform the overflow rect by the current transformation. */
bool hasTransform = IsTransformed();
if (hasTransform) {
Properties().Set(nsIFrame::PreTransformBBoxProperty(),
new nsRect(aOverflowAreas.VisualOverflow()));
Properties().Set(nsIFrame::PreTransformOverflowAreasProperty(),
new nsOverflowAreas(aOverflowAreas));
/* Since our size might not actually have been computed yet, we need to make sure that we use the
* correct dimensions by overriding the stored bounding rectangle with the value the caller has
* ensured us we'll use.
@ -6663,6 +6694,8 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
if (Preserves3DChildren()) {
ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
}
} else {
Properties().Delete(nsIFrame::PreTransformOverflowAreasProperty());
}
bool visualOverflowChanged =
@ -6823,15 +6856,8 @@ void
nsFrame::ConsiderChildOverflow(nsOverflowAreas& aOverflowAreas,
nsIFrame* aChildFrame)
{
const nsStyleDisplay* disp = GetStyleDisplay();
// check here also for hidden as table frames (table, tr and td) currently
// don't wrap their content into a scrollable frame if overflow is specified
// FIXME: Why do we check this here rather than in
// FinishAndStoreOverflow (where we check NS_STYLE_OVERFLOW_CLIP)?
if (!disp->IsTableClip()) {
aOverflowAreas.UnionWith(aChildFrame->GetOverflowAreas() +
aChildFrame->GetPosition());
}
aOverflowAreas.UnionWith(aChildFrame->GetOverflowAreas() +
aChildFrame->GetPosition());
}
/**
@ -7254,7 +7280,7 @@ nsFrame::GetPrefSize(nsBoxLayoutState& aState)
return metrics->mPrefSize;
}
if (IsCollapsed(aState))
if (IsCollapsed())
return size;
// get our size in CSS.
@ -7290,7 +7316,7 @@ nsFrame::GetMinSize(nsBoxLayoutState& aState)
return size;
}
if (IsCollapsed(aState))
if (IsCollapsed())
return size;
// get our size in CSS.
@ -7325,7 +7351,7 @@ nsFrame::GetMaxSize(nsBoxLayoutState& aState)
return size;
}
if (IsCollapsed(aState))
if (IsCollapsed())
return size;
size = nsBox::GetMaxSize(aState);
@ -7353,7 +7379,7 @@ nsFrame::GetBoxAscent(nsBoxLayoutState& aState)
if (!DoesNeedRecalc(metrics->mAscent))
return metrics->mAscent;
if (IsCollapsed(aState)) {
if (IsCollapsed()) {
metrics->mAscent = 0;
} else {
// Refresh our caches with new sizes.
@ -7379,7 +7405,7 @@ nsFrame::DoLayout(nsBoxLayoutState& aState)
rv = BoxReflow(aState, presContext, desiredSize, rendContext,
ourRect.x, ourRect.y, ourRect.width, ourRect.height);
if (IsCollapsed(aState)) {
if (IsCollapsed()) {
SetSize(nsSize(0, 0));
} else {
@ -7640,7 +7666,7 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState,
aDesiredSize, aX, aY, layoutFlags | NS_FRAME_NO_MOVE_FRAME);
// Save the ascent. (bug 103925)
if (IsCollapsed(aState)) {
if (IsCollapsed()) {
metrics->mAscent = 0;
} else {
if (aDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {

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

@ -346,6 +346,8 @@ public:
void DestroyAbsoluteFrames(nsIFrame* aDestructRoot);
virtual bool CanContinueTextRun() const;
virtual bool UpdateOverflow();
// Selection Methods
// XXX Doc me... (in nsIFrame.h puhleeze)
// XXX If these are selection specific, then the name should imply selection

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

@ -799,7 +799,7 @@ nsHTMLScrollFrame::GetPadding(nsMargin& aMargin)
}
bool
nsHTMLScrollFrame::IsCollapsed(nsBoxLayoutState& aBoxLayoutState)
nsHTMLScrollFrame::IsCollapsed()
{
// We're never collapsed in the box sense.
return false;
@ -3269,6 +3269,27 @@ static void LayoutAndInvalidate(nsBoxLayoutState& aState,
}
}
bool
nsGfxScrollFrameInner::UpdateOverflow()
{
nsIScrollableFrame* sf = do_QueryFrame(mOuter);
ScrollbarStyles ss = sf->GetScrollbarStyles();
if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN ||
ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN ||
GetScrollPosition() != nsPoint()) {
// If there are scrollbars, or we're not at the beginning of the pane,
// the scroll position may change. In this case, mark the frame as
// needing reflow.
mOuter->PresContext()->PresShell()->FrameNeedsReflow(
mOuter, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
}
// Scroll frames never have overflow area because they always clip their
// children, so return false.
return false;
}
void
nsGfxScrollFrameInner::AdjustScrollbarRectForResizer(
nsIFrame* aFrame, nsPresContext* aPresContext,

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

@ -245,6 +245,9 @@ public:
bool IsLTR() const;
bool IsScrollbarOnRight() const;
bool IsScrollingActive() const { return mScrollingActive || ShouldBuildLayer(); }
bool UpdateOverflow();
// adjust the scrollbar rectangle aRect to account for any visible resizer.
// aHasResizer specifies if there is a content resizer, however this method
// will also check if a widget resizer is present as well.
@ -385,7 +388,7 @@ public:
virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
NS_IMETHOD GetPadding(nsMargin& aPadding);
virtual bool IsCollapsed(nsBoxLayoutState& aBoxLayoutState);
virtual bool IsCollapsed();
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
@ -497,6 +500,9 @@ public:
virtual bool IsScrollingActive() {
return mInner.IsScrollingActive();
}
virtual bool UpdateOverflow() {
return mInner.UpdateOverflow();
}
// nsIStatefulFrame
NS_IMETHOD SaveState(SpecialStateID aStateID, nsPresState** aState) {
@ -732,6 +738,9 @@ public:
virtual bool IsScrollingActive() {
return mInner.IsScrollingActive();
}
virtual bool UpdateOverflow() {
return mInner.UpdateOverflow();
}
// nsIStatefulFrame
NS_IMETHOD SaveState(SpecialStateID aStateID, nsPresState** aState) {

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

@ -910,7 +910,8 @@ public:
NS_DECLARE_FRAME_PROPERTY(OutlineInnerRectProperty, DestroyRect)
NS_DECLARE_FRAME_PROPERTY(PreEffectsBBoxProperty, DestroyRect)
NS_DECLARE_FRAME_PROPERTY(PreTransformBBoxProperty, DestroyRect)
NS_DECLARE_FRAME_PROPERTY(PreTransformOverflowAreasProperty,
DestroyOverflowAreas)
// The initial overflow area passed to FinishAndStoreOverflow. This is only set
// on frames that Preserve3D(), and when at least one of the overflow areas
@ -1782,6 +1783,13 @@ public:
// XXX Maybe these three should be a separate interface?
/**
* Updates the overflow areas of the frame. This can be called if an
* overflow area of the frame's children has changed without reflowing.
* @return true if either of the overflow areas for this frame have changed.
*/
virtual bool UpdateOverflow() = 0;
/**
* Helper method used by block reflow to identify runs of text so
* that proper word-breaking can be done.
@ -2604,7 +2612,7 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()))
virtual nscoord GetFlex(nsBoxLayoutState& aBoxLayoutState) = 0;
virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0;
virtual bool IsCollapsed(nsBoxLayoutState& aBoxLayoutState) = 0;
virtual bool IsCollapsed() = 0;
// This does not alter the overflow area. If the caller is changing
// the box size, the caller is responsible for updating the overflow
// area. It's enough to just call Layout or SyncLayout on the

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

@ -876,6 +876,17 @@ nsMathMLContainerFrame::GatherAndStoreOverflow(nsHTMLReflowMetrics* aMetrics)
FinishAndStoreOverflow(aMetrics);
}
bool
nsMathMLContainerFrame::UpdateOverflow()
{
// Our overflow areas may have changed, so reflow the frame.
PresContext()->PresShell()->FrameNeedsReflow(
this, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
// As we're reflowing, there's no need to propagate this change.
return false;
}
nsresult
nsMathMLContainerFrame::ReflowChild(nsIFrame* aChildFrame,
nsPresContext* aPresContext,

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

@ -171,6 +171,8 @@ public:
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
virtual bool UpdateOverflow();
// Notification when an attribute is changed. The MathML module uses the
// following paradigm:
//

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

@ -437,7 +437,8 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther)
// FRAMECHANGE Structs: Display, XUL, Content, UserInterface,
// Visibility, Outline, TableBorder, Table, Text, UIReset, Quotes
nsChangeHint maxHint = nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
nsChangeHint_UpdateTransformLayer | nsChangeHint_UpdateOpacityLayer);
nsChangeHint_UpdateTransformLayer | nsChangeHint_UpdateOpacityLayer |
nsChangeHint_UpdateOverflow);
DO_STRUCT_DIFFERENCE(Display);
maxHint = nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |

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

@ -2238,15 +2238,17 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
else if (HasTransform()) {
/* Otherwise, if we've kept the property lying around and we already had a
* transform, we need to see whether or not we've changed the transform.
* If so, we need to do a reflow and a repaint. The reflow is to recompute
* the overflow rect (which probably changed if the transform changed)
* and to redraw within the bounds of that new overflow rect.
* If so, we need to recompute its overflow rect (which probably changed
* if the transform changed) and to redraw within the bounds of that new
* overflow rect.
*/
if (!mSpecifiedTransform != !aOther.mSpecifiedTransform ||
(mSpecifiedTransform && *mSpecifiedTransform != *aOther.mSpecifiedTransform))
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_NeedReflow,
(mSpecifiedTransform &&
*mSpecifiedTransform != *aOther.mSpecifiedTransform)) {
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_UpdateOverflow,
nsChangeHint_UpdateTransformLayer));
}
for (PRUint8 index = 0; index < 3; ++index)
if (mTransformOrigin[index] != aOther.mTransformOrigin[index]) {
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_NeedReflow,
@ -2295,8 +2297,10 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
nsChangeHint nsStyleDisplay::MaxDifference()
{
// All the parts of FRAMECHANGE are present above in CalcDifference.
return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE | nsChangeHint_UpdateOpacityLayer |
nsChangeHint_UpdateTransformLayer);
return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
nsChangeHint_UpdateOpacityLayer |
nsChangeHint_UpdateTransformLayer |
nsChangeHint_UpdateOverflow);
}
#endif

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

@ -618,6 +618,18 @@ void nsTableCellFrame::VerticallyAlignChild(nscoord aMaxAscent)
}
}
bool
nsTableCellFrame::UpdateOverflow()
{
nsRect bounds(nsPoint(0,0), GetSize());
bounds.Inflate(GetBorderOverflow());
nsOverflowAreas overflowAreas(bounds, bounds);
nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
return FinishAndStoreOverflow(overflowAreas, GetSize());
}
// Per CSS 2.1, we map 'sub', 'super', 'text-top', 'text-bottom',
// length, percentage, and calc() values to 'baseline'.
PRUint8

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

@ -240,6 +240,8 @@ public:
void DecorateForSelection(nsRenderingContext& aRenderingContext,
nsPoint aPt);
virtual bool UpdateOverflow();
protected:
/** implement abstract method on nsContainerFrame */
virtual PRIntn GetSkipSides() const;

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

@ -1848,6 +1848,24 @@ NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext,
return rv;
}
bool
nsTableFrame::UpdateOverflow()
{
nsRect bounds(nsPoint(0, 0), GetSize());
// As above in Reflow, make sure the table overflow area includes the table
// rect, and check for collapsed borders leaking out.
if (!GetStyleDisplay()->IsTableClip()) {
nsMargin bcMargin = GetExcludedOuterBCBorder();
bounds.Inflate(bcMargin);
}
nsOverflowAreas overflowAreas(bounds, bounds);
nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
return FinishAndStoreOverflow(overflowAreas, GetSize());
}
nsresult
nsTableFrame::ReflowTable(nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,

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

@ -506,6 +506,8 @@ public:
const nsRect& aOrigVisualOverflow,
bool aIsFirstReflow);
virtual bool UpdateOverflow();
protected:
/** protected constructor.

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

@ -652,7 +652,7 @@ nsGrid::GetFirstAndLastRow(nsBoxLayoutState& aState,
for (i=0; i < count; i++)
{
nsGridRow* row = GetRowAt(i,aIsHorizontal);
if (!row->IsCollapsed(aState)) {
if (!row->IsCollapsed()) {
aFirstIndex = i;
aFirstRow = row;
break;
@ -663,7 +663,7 @@ nsGrid::GetFirstAndLastRow(nsBoxLayoutState& aState,
for (i=count-1; i >= 0; i--)
{
nsGridRow* row = GetRowAt(i,aIsHorizontal);
if (!row->IsCollapsed(aState)) {
if (!row->IsCollapsed()) {
aLastIndex = i;
aLastRow = row;
break;
@ -706,7 +706,7 @@ nsGrid::GetRowOffsets(nsBoxLayoutState& aState, PRInt32 aIndex, nscoord& aTop, n
// borders padding into account
if (box && !row->mIsBogus)
{
if (!box->IsCollapsed(aState))
if (!box->IsCollapsed())
{
// get real border and padding. GetBorderAndPadding
// is redefined on nsGridRowLeafFrame. If we called it here
@ -771,7 +771,7 @@ nsGrid::GetRowOffsets(nsBoxLayoutState& aState, PRInt32 aIndex, nscoord& aTop, n
if (box)
{
// ignore collapsed children
if (!box->IsCollapsed(aState))
if (!box->IsCollapsed())
{
// include the margin of the columns. To the row
// at this point border/padding and margins all added
@ -846,7 +846,7 @@ nsGrid::GetPrefRowHeight(nsBoxLayoutState& aState, PRInt32 aIndex, bool aIsHoriz
nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
if (row->IsCollapsed(aState))
if (row->IsCollapsed())
return 0;
if (row->IsPrefSet())
@ -903,7 +903,7 @@ nsGrid::GetPrefRowHeight(nsBoxLayoutState& aState, PRInt32 aIndex, bool aIsHoriz
child = GetCellAt(aIndex,i);
// ignore collapsed children
if (!child->IsCollapsed(aState))
if (!child->IsCollapsed())
{
nsSize childSize = child->GetPrefSize(aState);
@ -923,7 +923,7 @@ nsGrid::GetMinRowHeight(nsBoxLayoutState& aState, PRInt32 aIndex, bool aIsHorizo
nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
if (row->IsCollapsed(aState))
if (row->IsCollapsed())
return 0;
if (row->IsMinSet())
@ -978,7 +978,7 @@ nsGrid::GetMinRowHeight(nsBoxLayoutState& aState, PRInt32 aIndex, bool aIsHorizo
child = GetCellAt(aIndex,i);
// ignore collapsed children
if (!child->IsCollapsed(aState))
if (!child->IsCollapsed())
{
nsSize childSize = child->GetMinSize(aState);
@ -998,7 +998,7 @@ nsGrid::GetMaxRowHeight(nsBoxLayoutState& aState, PRInt32 aIndex, bool aIsHorizo
nsGridRow* row = GetRowAt(aIndex, aIsHorizontal);
if (row->IsCollapsed(aState))
if (row->IsCollapsed())
return 0;
if (row->IsMaxSet())
@ -1053,7 +1053,7 @@ nsGrid::GetMaxRowHeight(nsBoxLayoutState& aState, PRInt32 aIndex, bool aIsHorizo
child = GetCellAt(aIndex,i);
// ignore collapsed children
if (!child->IsCollapsed(aState))
if (!child->IsCollapsed())
{
nsSize min = child->GetMinSize(aState);
nsSize childSize = nsBox::BoundsCheckMinMax(min, child->GetMaxSize(aState));

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

@ -150,10 +150,10 @@ nsGridCell::GetMaxSize(nsBoxLayoutState& aState)
bool
nsGridCell::IsCollapsed(nsBoxLayoutState& aState)
nsGridCell::IsCollapsed()
{
return ((mBoxInColumn && mBoxInColumn->IsCollapsed(aState)) ||
(mBoxInRow && mBoxInRow->IsCollapsed(aState)));
return ((mBoxInColumn && mBoxInColumn->IsCollapsed()) ||
(mBoxInRow && mBoxInRow->IsCollapsed()));
}

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

@ -67,7 +67,7 @@ public:
nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState);
nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState);
nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState);
bool IsCollapsed(nsBoxLayoutState& aBoxLayoutState);
bool IsCollapsed();
// accessors
nsIBox* GetBoxInColumn() { return mBoxInColumn; }

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

@ -82,8 +82,8 @@ nsGridRow::~nsGridRow()
}
bool
nsGridRow::IsCollapsed(nsBoxLayoutState& aState)
nsGridRow::IsCollapsed()
{
return mBox && mBox->IsCollapsed(aState);
return mBox && mBox->IsCollapsed();
}

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

@ -68,7 +68,7 @@ public:
bool IsMaxSet() { return (mMax != -1); }
bool IsFlexSet() { return (mFlex != -1); }
bool IsOffsetSet() { return (mTop != -1 && mBottom != -1); }
bool IsCollapsed(nsBoxLayoutState& aState);
bool IsCollapsed();
public:

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

@ -170,7 +170,7 @@ nsGridRowLeafLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, ns
nscoord bottomMargin = column->mBottomMargin;
if (box)
collapsed = box->IsCollapsed(aState);
collapsed = box->IsCollapsed();
pref = pref - (left + right);
if (pref < 0)

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

@ -53,6 +53,7 @@
#include "nsIDocument.h"
#include "nsITheme.h"
#include "nsIServiceManager.h"
#include "nsIViewManager.h"
#include "nsBoxLayout.h"
#include "FrameLayerBuilder.h"
@ -435,7 +436,7 @@ nsBox::GetPrefSize(nsBoxLayoutState& aState)
nsSize pref(0,0);
DISPLAY_PREF_SIZE(this, pref);
if (IsCollapsed(aState))
if (IsCollapsed())
return pref;
AddBorderAndPadding(pref);
@ -455,7 +456,7 @@ nsBox::GetMinSize(nsBoxLayoutState& aState)
nsSize min(0,0);
DISPLAY_MIN_SIZE(this, min);
if (IsCollapsed(aState))
if (IsCollapsed())
return min;
AddBorderAndPadding(min);
@ -478,7 +479,7 @@ nsBox::GetMaxSize(nsBoxLayoutState& aState)
nsSize maxSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
DISPLAY_MAX_SIZE(this, maxSize);
if (IsCollapsed(aState))
if (IsCollapsed())
return maxSize;
AddBorderAndPadding(maxSize);
@ -520,14 +521,14 @@ nsIFrame::GetOrdinal(nsBoxLayoutState& aState)
nscoord
nsBox::GetBoxAscent(nsBoxLayoutState& aState)
{
if (IsCollapsed(aState))
if (IsCollapsed())
return 0;
return GetPrefSize(aState).height;
}
bool
nsBox::IsCollapsed(nsBoxLayoutState& aState)
nsBox::IsCollapsed()
{
return GetStyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE;
}
@ -563,9 +564,7 @@ nsresult
nsBox::SyncLayout(nsBoxLayoutState& aState)
{
/*
bool collapsed = false;
IsCollapsed(aState, collapsed);
if (collapsed) {
if (IsCollapsed()) {
CollapseChild(aState, this, true);
return NS_OK;
}
@ -595,17 +594,13 @@ nsBox::SyncLayout(nsBoxLayoutState& aState)
else {
nsRect rect(nsPoint(0, 0), GetSize());
nsOverflowAreas overflowAreas(rect, rect);
if (!DoesClipChildren() && !IsCollapsed(aState)) {
if (!DoesClipChildren() && !IsCollapsed()) {
// See if our child frames caused us to overflow after being laid
// out. If so, store the overflow area. This normally can't happen
// in XUL, but it can happen with the CSS 'outline' property and
// possibly with other exotic stuff (e.g. relatively positioned
// frames in HTML inside XUL).
for (nsIFrame* kid = GetChildBox(); kid; kid = kid->GetNextBox()) {
nsOverflowAreas kidOverflow =
kid->GetOverflowAreas() + kid->GetPosition();
overflowAreas.UnionWith(kidOverflow);
}
nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
}
FinishAndStoreOverflow(overflowAreas, GetSize());

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

@ -62,7 +62,7 @@ public:
virtual nsSize GetMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState);
virtual bool IsCollapsed(nsBoxLayoutState& aBoxLayoutState);
virtual bool IsCollapsed();
virtual void SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
bool aRemoveOverflowAreas = false);

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

@ -779,7 +779,7 @@ nsBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState)
PropagateDebug(aBoxLayoutState);
#endif
if (IsCollapsed(aBoxLayoutState))
if (IsCollapsed())
return size;
// if the size was not completely redefined in CSS then ask our children
@ -815,7 +815,7 @@ nsBoxFrame::GetBoxAscent(nsBoxLayoutState& aBoxLayoutState)
PropagateDebug(aBoxLayoutState);
#endif
if (IsCollapsed(aBoxLayoutState))
if (IsCollapsed())
return 0;
if (mLayoutManager)
@ -842,7 +842,7 @@ nsBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
PropagateDebug(aBoxLayoutState);
#endif
if (IsCollapsed(aBoxLayoutState))
if (IsCollapsed())
return size;
// if the size was not completely redefined in CSS then ask our children
@ -882,7 +882,7 @@ nsBoxFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState)
PropagateDebug(aBoxLayoutState);
#endif
if (IsCollapsed(aBoxLayoutState))
if (IsCollapsed())
return size;
// if the size was not completely redefined in CSS then ask our children
@ -1502,7 +1502,7 @@ nsBoxFrame::PaintXULDebugOverlay(nsRenderingContext& aRenderingContext,
nsBoxLayoutState state(GetPresContext());
nscoord flex = kid->GetFlex(state);
if (!kid->IsCollapsed(state)) {
if (!kid->IsCollapsed()) {
aRenderingContext.SetColor(NS_RGB(255,255,255));
if (isHorizontal)

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

@ -1321,7 +1321,7 @@ nsMenuFrame::AppendFrames(ChildListID aListID,
bool
nsMenuFrame::SizeToPopup(nsBoxLayoutState& aState, nsSize& aSize)
{
if (!IsCollapsed(aState)) {
if (!IsCollapsed()) {
bool widthSet, heightSet;
nsSize tmpSize(-1, 0);
nsIBox::AddCSSPrefSize(this, tmpSize, widthSet, heightSet);

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

@ -204,7 +204,7 @@ nsSprocketLayout::Layout(nsIBox* aBox, nsBoxLayoutState& aState)
{
// See if we are collapsed. If we are, then simply iterate over all our
// children and give them a rect of 0 width and height.
if (aBox->IsCollapsed(aState)) {
if (aBox->IsCollapsed()) {
nsIBox* child = aBox->GetChildBox();
while(child)
{
@ -741,7 +741,7 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
flex = child->GetFlex(aState);
currentBox->flex = flex;
currentBox->collapsed = child->IsCollapsed(aState);
currentBox->collapsed = child->IsCollapsed();
} else {
flex = start->flex;
start = start->next;
@ -773,7 +773,7 @@ nsSprocketLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBox
nsSize minSize(0,0);
nsSize maxSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE);
nscoord ascent = 0;
bool collapsed = child->IsCollapsed(aState);
bool collapsed = child->IsCollapsed();
if (!collapsed) {
// only one flexible child? Cool we will just make its preferred size
@ -1361,7 +1361,7 @@ nsSprocketLayout::GetPrefSize(nsIBox* aBox, nsBoxLayoutState& aState)
while (child)
{
// ignore collapsed children
if (!child->IsCollapsed(aState))
if (!child->IsCollapsed())
{
nsSize pref = child->GetPrefSize(aState);
AddMargin(child, pref);
@ -1418,7 +1418,7 @@ nsSprocketLayout::GetMinSize(nsIBox* aBox, nsBoxLayoutState& aState)
while (child)
{
// ignore collapsed children
if (!child->IsCollapsed(aState))
if (!child->IsCollapsed())
{
nsSize min = child->GetMinSize(aState);
nsSize pref(0,0);
@ -1487,7 +1487,7 @@ nsSprocketLayout::GetMaxSize(nsIBox* aBox, nsBoxLayoutState& aState)
while (child)
{
// ignore collapsed children
if (!child->IsCollapsed(aState))
if (!child->IsCollapsed())
{
// if completely redefined don't even ask our child for its size.
nsSize min = child->GetMinSize(aState);
@ -1548,7 +1548,7 @@ nsSprocketLayout::GetAscent(nsIBox* aBox, nsBoxLayoutState& aState)
while (child)
{
// ignore collapsed children
//if (!child->IsCollapsed(aState))
//if (!child->IsCollapsed())
//{
// if completely redefined don't even ask our child for its size.
nscoord ascent = child->GetBoxAscent(aState);