mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 539356 - Make the table code use rect invalidation to avoid over invalidation. r=roc
This commit is contained in:
parent
5eaaebce0e
commit
9a9168f55a
@ -472,6 +472,14 @@ nsFrameManager::RemoveFrame(ChildListID aListID,
|
||||
bool wasDestroyingFrames = mIsDestroyingFrames;
|
||||
mIsDestroyingFrames = true;
|
||||
|
||||
// In case the reflow doesn't invalidate anything since it just leaves
|
||||
// a gap where the old frame was, we invalidate it here. (This is
|
||||
// reasonably likely to happen when removing a last child in a way
|
||||
// that doesn't change the size of the parent.)
|
||||
// This has to sure to invalidate the entire overflow rect; this
|
||||
// is important in the presence of absolute positioning
|
||||
aOldFrame->InvalidateFrameForRemoval();
|
||||
|
||||
NS_ASSERTION(!aOldFrame->GetPrevContinuation() ||
|
||||
// exception for nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames
|
||||
aOldFrame->GetType() == nsGkAtoms::textFrame,
|
||||
|
@ -4794,30 +4794,35 @@ nsIFrame::ClearInvalidationStateBits()
|
||||
NS_FRAME_ALL_DESCENDANTS_NEED_PAINT);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateFrame()
|
||||
static void InvalidateFrameInternal(nsIFrame *aFrame)
|
||||
{
|
||||
AddStateBits(NS_FRAME_NEEDS_PAINT);
|
||||
nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(this);
|
||||
aFrame->AddStateBits(NS_FRAME_NEEDS_PAINT);
|
||||
nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
|
||||
while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) {
|
||||
parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT);
|
||||
parent = nsLayoutUtils::GetCrossDocParentFrame(parent);
|
||||
}
|
||||
if (!parent) {
|
||||
SchedulePaint();
|
||||
aFrame->SchedulePaint();
|
||||
}
|
||||
if (HasAnyStateBits(NS_FRAME_HAS_INVALID_RECT)) {
|
||||
Properties().Delete(InvalidationRect());
|
||||
RemoveStateBits(NS_FRAME_HAS_INVALID_RECT);
|
||||
if (aFrame->HasAnyStateBits(NS_FRAME_HAS_INVALID_RECT)) {
|
||||
aFrame->Properties().Delete(nsIFrame::InvalidationRect());
|
||||
aFrame->RemoveStateBits(NS_FRAME_HAS_INVALID_RECT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateFrame()
|
||||
{
|
||||
InvalidateFrameInternal(this);
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::InvalidateFrameWithRect(const nsRect& aRect)
|
||||
{
|
||||
bool alreadyInvalid = false;
|
||||
if (!HasAnyStateBits(NS_FRAME_NEEDS_PAINT)) {
|
||||
InvalidateFrame();
|
||||
InvalidateFrameInternal(this);
|
||||
} else {
|
||||
alreadyInvalid = true;
|
||||
}
|
||||
|
@ -2203,6 +2203,12 @@ public:
|
||||
* the out-of-flow frames.
|
||||
*/
|
||||
void InvalidateFrameSubtree();
|
||||
|
||||
/**
|
||||
* Called when a frame is about to be removed and needs to be invalidated.
|
||||
* Normally does nothing since DLBI handles removed frames.
|
||||
*/
|
||||
virtual void InvalidateFrameForRemoval() {}
|
||||
|
||||
/**
|
||||
* Checks if a frame has had InvalidateFrame() called on it since the
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsTextFrame.h"
|
||||
#include "FrameLayerBuilder.h"
|
||||
|
||||
//TABLECELL SELECTION
|
||||
#include "nsFrameSelection.h"
|
||||
@ -396,6 +397,21 @@ nsDisplayTableCellBackground::GetBounds(nsDisplayListBuilder* aBuilder,
|
||||
return nsDisplayItem::GetBounds(aBuilder, aSnap);
|
||||
}
|
||||
|
||||
void nsTableCellFrame::InvalidateFrame(uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrame(aDisplayItemKey);
|
||||
GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
||||
void nsTableCellFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
|
||||
// If we have filters applied that would affects our bounds, then
|
||||
// we get an inactive layer created and this is computed
|
||||
// within FrameLayerBuilder
|
||||
GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
||||
static void
|
||||
PaintTableCellSelection(nsIFrame* aFrame, nsRenderingContext* aCtx,
|
||||
const nsRect& aRect, nsPoint aPt)
|
||||
@ -561,6 +577,11 @@ void nsTableCellFrame::VerticallyAlignChild(nscoord aMaxAscent)
|
||||
// if the content is larger than the cell height align from top
|
||||
kidYTop = NS_MAX(0, kidYTop);
|
||||
|
||||
if (kidYTop != kidRect.y) {
|
||||
// Invalidate at the old position first
|
||||
firstKid->InvalidateFrameSubtree();
|
||||
}
|
||||
|
||||
firstKid->SetPosition(nsPoint(kidRect.x, kidYTop));
|
||||
nsHTMLReflowMetrics desiredSize;
|
||||
desiredSize.width = mRect.width;
|
||||
@ -575,6 +596,9 @@ void nsTableCellFrame::VerticallyAlignChild(nscoord aMaxAscent)
|
||||
// Make sure any child views are correctly positioned. We know the inner table
|
||||
// cell won't have a view
|
||||
nsContainerFrame::PositionChildViews(firstKid);
|
||||
|
||||
// Invalidate new overflow rect
|
||||
firstKid->InvalidateFrameSubtree();
|
||||
}
|
||||
if (HasView()) {
|
||||
nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this,
|
||||
@ -865,6 +889,9 @@ NS_METHOD nsTableCellFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
nsPoint kidOrigin(leftInset, topInset);
|
||||
nsRect origRect = firstKid->GetRect();
|
||||
nsRect origVisualOverflow = firstKid->GetVisualOverflowRect();
|
||||
bool firstReflow = (firstKid->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
|
||||
ReflowChild(firstKid, aPresContext, kidSize, kidReflowState,
|
||||
kidOrigin.x, kidOrigin.y, NS_FRAME_INVALIDATE_ON_MOVE, aStatus);
|
||||
@ -875,6 +902,11 @@ NS_METHOD nsTableCellFrame::Reflow(nsPresContext* aPresContext,
|
||||
printf("Set table cell incomplete %p\n", static_cast<void*>(this));
|
||||
}
|
||||
|
||||
// XXXbz is this invalidate actually needed, really?
|
||||
if (GetStateBits() & NS_FRAME_IS_DIRTY) {
|
||||
InvalidateFrameSubtree();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
DebugCheckChildSize(firstKid, kidSize, availSize);
|
||||
#endif
|
||||
@ -894,6 +926,9 @@ NS_METHOD nsTableCellFrame::Reflow(nsPresContext* aPresContext,
|
||||
FinishReflowChild(firstKid, aPresContext, &kidReflowState, kidSize,
|
||||
kidOrigin.x, kidOrigin.y, 0);
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(firstKid, origRect, origVisualOverflow,
|
||||
firstReflow);
|
||||
|
||||
// first, compute the height which can be set w/o being restricted by aMaxSize.height
|
||||
nscoord cellHeight = kidSize.height;
|
||||
|
||||
@ -926,6 +961,13 @@ NS_METHOD nsTableCellFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
// If our parent is in initial reflow, it'll handle invalidating our
|
||||
// entire overflow rect.
|
||||
if (!(GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
|
||||
nsSize(aDesiredSize.width, aDesiredSize.height) != mRect.Size()) {
|
||||
InvalidateFrame();
|
||||
}
|
||||
|
||||
// remember the desired size for this reflow
|
||||
SetDesiredSize(aDesiredSize);
|
||||
|
||||
|
@ -211,12 +211,9 @@ public:
|
||||
|
||||
virtual bool UpdateOverflow();
|
||||
|
||||
virtual void InvalidateFrame()
|
||||
{
|
||||
nsIFrame::InvalidateFrame();
|
||||
nsTableFrame *tableFrame = nsTableFrame::GetTableFrame(this);
|
||||
tableFrame->InvalidateFrame();
|
||||
}
|
||||
virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameForRemoval() MOZ_OVERRIDE { InvalidateFrameSubtree(); }
|
||||
|
||||
protected:
|
||||
/** implement abstract method on nsContainerFrame */
|
||||
|
@ -191,10 +191,20 @@ nsTableColFrame::GetSplittableType() const
|
||||
}
|
||||
|
||||
void
|
||||
nsTableColFrame::InvalidateFrame()
|
||||
nsTableColFrame::InvalidateFrame(uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrame();
|
||||
nsTableFrame *tableFrame = nsTableFrame::GetTableFrame(this);
|
||||
tableFrame->InvalidateFrame();
|
||||
nsIFrame::InvalidateFrame(aDisplayItemKey);
|
||||
GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
||||
void
|
||||
nsTableColFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
|
||||
|
||||
// If we have filters applied that would affects our bounds, then
|
||||
// we get an inactive layer created and this is computed
|
||||
// within FrameLayerBuilder
|
||||
GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,9 @@ public:
|
||||
return mFinalWidth;
|
||||
}
|
||||
|
||||
virtual void InvalidateFrame();
|
||||
virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameForRemoval() MOZ_OVERRIDE { InvalidateFrameSubtree(); }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -465,11 +465,20 @@ nsTableColGroupFrame::GetType() const
|
||||
}
|
||||
|
||||
void
|
||||
nsTableColGroupFrame::InvalidateFrame()
|
||||
nsTableColGroupFrame::InvalidateFrame(uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrame();
|
||||
nsTableFrame *tableFrame = nsTableFrame::GetTableFrame(this);
|
||||
tableFrame->InvalidateFrame();
|
||||
nsIFrame::InvalidateFrame(aDisplayItemKey);
|
||||
GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
||||
void
|
||||
nsTableColGroupFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
|
||||
// If we have filters applied that would affects our bounds, then
|
||||
// we get an inactive layer created and this is computed
|
||||
// within FrameLayerBuilder
|
||||
GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -197,7 +197,9 @@ public:
|
||||
void SetContinuousBCBorderWidth(uint8_t aForSide,
|
||||
BCPixelSize aPixelValue);
|
||||
|
||||
virtual void InvalidateFrame();
|
||||
virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameForRemoval() MOZ_OVERRIDE { InvalidateFrameSubtree(); }
|
||||
|
||||
protected:
|
||||
nsTableColGroupFrame(nsStyleContext* aContext);
|
||||
|
@ -1391,7 +1391,7 @@ nsTableFrame::ProcessRowInserted(nscoord aNewHeight)
|
||||
if (rowFrame->IsFirstInserted()) {
|
||||
rowFrame->SetFirstInserted(false);
|
||||
// damage the table from the 1st row inserted to the end of the table
|
||||
InvalidateFrame();
|
||||
nsIFrame::InvalidateFrame();
|
||||
// XXXbz didn't we do this up front? Why do we need to do it again?
|
||||
SetRowInserted(false);
|
||||
return; // found it, so leave
|
||||
@ -1806,6 +1806,11 @@ NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
aDesiredSize.mOverflowAreas.UnionAllWith(tableRect);
|
||||
|
||||
if ((GetStateBits() & NS_FRAME_FIRST_REFLOW) ||
|
||||
nsSize(aDesiredSize.width, aDesiredSize.height) != mRect.Size()) {
|
||||
nsIFrame::InvalidateFrame();
|
||||
}
|
||||
|
||||
FinishAndStoreOverflow(&aDesiredSize);
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
return rv;
|
||||
@ -2491,10 +2496,16 @@ void nsTableFrame::PlaceChild(nsTableReflowState& aReflowState,
|
||||
const nsRect& aOriginalKidRect,
|
||||
const nsRect& aOriginalKidVisualOverflow)
|
||||
{
|
||||
bool isFirstReflow =
|
||||
(aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
|
||||
// Place and size the child
|
||||
FinishReflowChild(aKidFrame, PresContext(), nullptr, aKidDesiredSize,
|
||||
aReflowState.x, aReflowState.y, 0);
|
||||
|
||||
InvalidateTableFrame(aKidFrame, aOriginalKidRect, aOriginalKidVisualOverflow,
|
||||
isFirstReflow);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += aKidDesiredSize.height;
|
||||
|
||||
@ -2929,9 +2940,13 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
||||
aReflowState.y += cellSpacingY;
|
||||
nsRect kidRect = kidFrame->GetRect();
|
||||
if (kidRect.y != aReflowState.y) {
|
||||
// invalidate the old position
|
||||
kidFrame->InvalidateFrameSubtree();
|
||||
kidRect.y = aReflowState.y;
|
||||
kidFrame->SetRect(kidRect); // move to the new position
|
||||
RePositionViews(kidFrame);
|
||||
// invalidate the new position
|
||||
kidFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
aReflowState.y += kidRect.height;
|
||||
|
||||
@ -3105,13 +3120,18 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
||||
amountUsedByRG += amountForRow;
|
||||
//rowFrame->DidResize();
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
|
||||
rgFrame->InvalidateFrameWithRect(oldRowRect);
|
||||
rgFrame->InvalidateFrame();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (amountUsed > 0 && yOriginRow != rowRect.y &&
|
||||
!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
rowFrame->InvalidateFrameSubtree();
|
||||
rowFrame->SetPosition(nsPoint(rowRect.x, yOriginRow));
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
rowFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
@ -3119,18 +3139,28 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
if (amountUsed > 0) {
|
||||
if (rgRect.y != yOriginRG) {
|
||||
rgFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
|
||||
nsRect origRgRect = rgRect;
|
||||
nsRect origRgVisualOverflow = rgFrame->GetVisualOverflowRect();
|
||||
|
||||
rgRect.y = yOriginRG;
|
||||
rgRect.height += amountUsedByRG;
|
||||
|
||||
rgFrame->SetRect(rgRect);
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(rgFrame, origRgRect,
|
||||
origRgVisualOverflow, false);
|
||||
}
|
||||
}
|
||||
else if (amountUsed > 0 && yOriginRG != rgRect.y) {
|
||||
rgFrame->InvalidateFrameSubtree();
|
||||
rgFrame->SetPosition(nsPoint(rgRect.x, yOriginRG));
|
||||
// Make sure child views are properly positioned
|
||||
nsTableFrame::RePositionViews(rgFrame);
|
||||
rgFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
yOriginRG = yEndRG;
|
||||
}
|
||||
@ -3238,6 +3268,10 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
||||
? aAmount - amountUsed : NSToCoordRound(((float)(heightToDistribute)) * ratio);
|
||||
amountForRow = NS_MIN(amountForRow, aAmount - amountUsed);
|
||||
|
||||
if (yOriginRow != rowRect.y) {
|
||||
rowFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
|
||||
// update the row height
|
||||
nsRect newRowRect(rowRect.x, yOriginRow, rowRect.width,
|
||||
rowRect.height + amountForRow);
|
||||
@ -3251,11 +3285,16 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
||||
NS_ASSERTION((amountUsed <= aAmount), "invalid row allocation");
|
||||
//rowFrame->DidResize();
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(rowFrame, rowRect, rowVisualOverflow,
|
||||
false);
|
||||
}
|
||||
else {
|
||||
if (amountUsed > 0 && yOriginRow != rowRect.y) {
|
||||
rowFrame->InvalidateFrameSubtree();
|
||||
rowFrame->SetPosition(nsPoint(rowRect.x, yOriginRow));
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
rowFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
@ -3263,15 +3302,24 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
if (amountUsed > 0) {
|
||||
if (rgRect.y != yOriginRG) {
|
||||
rgFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
|
||||
rgFrame->SetRect(nsRect(rgRect.x, yOriginRG, rgRect.width,
|
||||
rgRect.height + amountUsedByRG));
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(rgFrame, rgRect, rgVisualOverflow,
|
||||
false);
|
||||
}
|
||||
// Make sure child views are properly positioned
|
||||
}
|
||||
else if (amountUsed > 0 && yOriginRG != rgRect.y) {
|
||||
rgFrame->InvalidateFrameSubtree();
|
||||
rgFrame->SetPosition(nsPoint(rgRect.x, yOriginRG));
|
||||
// Make sure child views are properly positioned
|
||||
nsTableFrame::RePositionViews(rgFrame);
|
||||
rgFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
yOriginRG = yEndRG;
|
||||
}
|
||||
@ -7183,3 +7231,45 @@ bool nsTableFrame::RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsTableFrame::InvalidateTableFrame(nsIFrame* aFrame,
|
||||
const nsRect& aOrigRect,
|
||||
const nsRect& aOrigVisualOverflow,
|
||||
bool aIsFirstReflow)
|
||||
{
|
||||
nsIFrame* parent = aFrame->GetParent();
|
||||
NS_ASSERTION(parent, "What happened here?");
|
||||
|
||||
if (parent->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
|
||||
// Don't bother; we'll invalidate the parent's overflow rect when
|
||||
// we finish reflowing it.
|
||||
return;
|
||||
}
|
||||
|
||||
// The part that looks at both the rect and the overflow rect is a
|
||||
// bit of a hack. See nsBlockFrame::ReflowLine for an eloquent
|
||||
// description of its hackishness.
|
||||
//
|
||||
// This doesn't really make sense now that we have DLBI.
|
||||
// This code can probably be simplified a fair bit.
|
||||
nsRect visualOverflow = aFrame->GetVisualOverflowRect();
|
||||
if (aIsFirstReflow ||
|
||||
aOrigRect.TopLeft() != aFrame->GetPosition() ||
|
||||
aOrigVisualOverflow.TopLeft() != visualOverflow.TopLeft()) {
|
||||
// Invalidate the old and new overflow rects. Note that if the
|
||||
// frame moved, we can't just use aOrigVisualOverflow, since it's in
|
||||
// coordinates relative to the old position. So invalidate via
|
||||
// aFrame's parent, and reposition that overflow rect to the right
|
||||
// place.
|
||||
// XXXbz this doesn't handle outlines, does it?
|
||||
aFrame->InvalidateFrame();
|
||||
parent->InvalidateFrameWithRect(aOrigVisualOverflow + aOrigRect.TopLeft());
|
||||
} else {
|
||||
aFrame->InvalidateFrameWithRect(aOrigVisualOverflow);;
|
||||
aFrame->InvalidateFrame();
|
||||
parent->InvalidateFrameWithRect(aOrigRect);;
|
||||
parent->InvalidateFrame();
|
||||
}
|
||||
}
|
||||
|
@ -464,6 +464,23 @@ public:
|
||||
bool HasCellSpanningPctCol() const;
|
||||
void SetHasCellSpanningPctCol(bool aValue);
|
||||
|
||||
/**
|
||||
* To be called on a frame by its parent after setting its size/position and
|
||||
* calling DidReflow (possibly via FinishReflowChild()). This can also be
|
||||
* used for child frames which are not being reflowed but did have their size
|
||||
* or position changed.
|
||||
*
|
||||
* @param aFrame The frame to invalidate
|
||||
* @param aOrigRect The original rect of aFrame (before the change).
|
||||
* @param aOrigVisualOverflow The original overflow rect of aFrame.
|
||||
* @param aIsFirstReflow True if the size/position change is due to the
|
||||
* first reflow of aFrame.
|
||||
*/
|
||||
static void InvalidateTableFrame(nsIFrame* aFrame,
|
||||
const nsRect& aOrigRect,
|
||||
const nsRect& aOrigVisualOverflow,
|
||||
bool aIsFirstReflow);
|
||||
|
||||
virtual bool UpdateOverflow();
|
||||
|
||||
protected:
|
||||
|
@ -916,6 +916,21 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowState *innerRS =
|
||||
static_cast<nsHTMLReflowState*>((void*) innerRSSpace);
|
||||
|
||||
nsRect origInnerRect = InnerTableFrame()->GetRect();
|
||||
nsRect origInnerVisualOverflow = InnerTableFrame()->GetVisualOverflowRect();
|
||||
bool innerFirstReflow =
|
||||
(InnerTableFrame()->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
nsRect origCaptionRect;
|
||||
nsRect origCaptionVisualOverflow;
|
||||
bool captionFirstReflow;
|
||||
if (mCaptionFrames.NotEmpty()) {
|
||||
origCaptionRect = mCaptionFrames.FirstChild()->GetRect();
|
||||
origCaptionVisualOverflow =
|
||||
mCaptionFrames.FirstChild()->GetVisualOverflowRect();
|
||||
captionFirstReflow =
|
||||
(mCaptionFrames.FirstChild()->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
}
|
||||
|
||||
// ComputeAutoSize has to match this logic.
|
||||
if (captionSide == NO_SIDE) {
|
||||
// We don't have a caption.
|
||||
@ -1037,6 +1052,14 @@ NS_METHOD nsTableOuterFrame::Reflow(nsPresContext* aPresContext,
|
||||
innerOrigin.x, innerOrigin.y, 0);
|
||||
innerRS->~nsHTMLReflowState();
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(InnerTableFrame(), origInnerRect,
|
||||
origInnerVisualOverflow, innerFirstReflow);
|
||||
if (mCaptionFrames.NotEmpty()) {
|
||||
nsTableFrame::InvalidateTableFrame(mCaptionFrames.FirstChild(), origCaptionRect,
|
||||
origCaptionVisualOverflow,
|
||||
captionFirstReflow);
|
||||
}
|
||||
|
||||
UpdateReflowMetrics(captionSide, aDesiredSize, innerMargin, captionMargin);
|
||||
FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aOuterRS, aStatus);
|
||||
|
||||
|
@ -335,9 +335,13 @@ nsTableRowFrame::DidResize()
|
||||
|
||||
// resize the cell's height
|
||||
nsRect cellRect = cellFrame->GetRect();
|
||||
nsRect cellVisualOverflow = cellFrame->GetVisualOverflowRect();
|
||||
if (cellRect.height != cellHeight)
|
||||
{
|
||||
cellFrame->SetSize(nsSize(cellRect.width, cellHeight));
|
||||
nsTableFrame::InvalidateTableFrame(cellFrame, cellRect,
|
||||
cellVisualOverflow,
|
||||
false);
|
||||
}
|
||||
|
||||
// realign cell content based on the new height. We might be able to
|
||||
@ -834,6 +838,9 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
|
||||
|
||||
// Reflow the child frame
|
||||
nsRect kidRect = kidFrame->GetRect();
|
||||
nsRect kidVisualOverflow = kidFrame->GetVisualOverflowRect();
|
||||
bool firstReflow =
|
||||
(kidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
|
||||
if (doReflowChild) {
|
||||
// Calculate the available width for the table cell using the known column widths
|
||||
@ -923,6 +930,9 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
|
||||
|
||||
FinishReflowChild(kidFrame, aPresContext, nullptr, desiredSize, x, 0, 0);
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(kidFrame, kidRect, kidVisualOverflow,
|
||||
firstReflow);
|
||||
|
||||
x += desiredSize.width;
|
||||
}
|
||||
else {
|
||||
@ -1016,6 +1026,13 @@ nsTableRowFrame::Reflow(nsPresContext* aPresContext,
|
||||
// just set our width to what was available. The table will calculate the width and not use our value.
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
|
||||
// If our parent is in initial reflow, it'll handle invalidating our
|
||||
// entire overflow rect.
|
||||
if (!(GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
|
||||
nsSize(aDesiredSize.width, aDesiredSize.height) != mRect.Size()) {
|
||||
InvalidateFrame();
|
||||
}
|
||||
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
return rv;
|
||||
}
|
||||
@ -1062,6 +1079,11 @@ nsTableRowFrame::ReflowCellFrame(nsPresContext* aPresContext,
|
||||
aCellFrame->VerticallyAlignChild(mMaxCellAscent);
|
||||
}
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(aCellFrame, cellRect,
|
||||
cellVisualOverflow,
|
||||
(aCellFrame->GetStateBits() &
|
||||
NS_FRAME_FIRST_REFLOW) != 0);
|
||||
|
||||
aCellFrame->DidReflow(aPresContext, nullptr, NS_FRAME_REFLOW_FINISHED);
|
||||
|
||||
return desiredSize.height;
|
||||
@ -1087,6 +1109,8 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
|
||||
}
|
||||
|
||||
nsRect rowRect = GetRect();
|
||||
nsRect oldRect = rowRect;
|
||||
nsRect oldVisualOverflow = GetVisualOverflowRect();
|
||||
|
||||
rowRect.y -= aRowOffset;
|
||||
rowRect.width = aWidth;
|
||||
@ -1215,6 +1239,12 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
|
||||
nsSize(cRect.width, cRect.height));
|
||||
nsTableFrame::RePositionViews(cellFrame);
|
||||
ConsiderChildOverflow(overflow, cellFrame);
|
||||
|
||||
if (aRowOffset == 0) {
|
||||
nsTableFrame::InvalidateTableFrame(cellFrame, oldCellRect,
|
||||
oldCellVisualOverflow,
|
||||
false);
|
||||
}
|
||||
}
|
||||
kidFrame = iter.Next(); // Get the next child
|
||||
}
|
||||
@ -1225,6 +1255,7 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset,
|
||||
FinishAndStoreOverflow(overflow, nsSize(rowRect.width, rowRect.height));
|
||||
|
||||
nsTableFrame::RePositionViews(this);
|
||||
nsTableFrame::InvalidateTableFrame(this, oldRect, oldVisualOverflow, false);
|
||||
return shift;
|
||||
}
|
||||
|
||||
@ -1352,11 +1383,20 @@ void nsTableRowFrame::InitHasCellWithStyleHeight(nsTableFrame* aTableFrame)
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::InvalidateFrame()
|
||||
nsTableRowFrame::InvalidateFrame(uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrame();
|
||||
nsTableFrame *tableFrame = nsTableFrame::GetTableFrame(this);
|
||||
tableFrame->InvalidateFrame();
|
||||
nsIFrame::InvalidateFrame(aDisplayItemKey);
|
||||
GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
|
||||
// If we have filters applied that would affects our bounds, then
|
||||
// we get an inactive layer created and this is computed
|
||||
// within FrameLayerBuilder
|
||||
GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
||||
/* ----- global methods ----- */
|
||||
|
@ -224,7 +224,9 @@ public:
|
||||
void SetContinuousBCBorderWidth(uint8_t aForSide,
|
||||
BCPixelSize aPixelValue);
|
||||
|
||||
virtual void InvalidateFrame();
|
||||
virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameForRemoval() MOZ_OVERRIDE { InvalidateFrameSubtree(); }
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
virtual already_AddRefed<Accessible> CreateAccessible() MOZ_OVERRIDE;
|
||||
|
@ -254,10 +254,16 @@ nsTableRowGroupFrame::PlaceChild(nsPresContext* aPresContext,
|
||||
const nsRect& aOriginalKidRect,
|
||||
const nsRect& aOriginalKidVisualOverflow)
|
||||
{
|
||||
bool isFirstReflow =
|
||||
(aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
||||
|
||||
// Place and size the child
|
||||
FinishReflowChild(aKidFrame, aPresContext, nullptr, aDesiredSize, 0,
|
||||
aReflowState.y, 0);
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(aKidFrame, aOriginalKidRect,
|
||||
aOriginalKidVisualOverflow, isFirstReflow);
|
||||
|
||||
// Adjust the running y-offset
|
||||
aReflowState.y += aDesiredSize.height;
|
||||
|
||||
@ -743,6 +749,7 @@ nsTableRowGroupFrame::CalculateRowHeights(nsPresContext* aPresContext,
|
||||
// update the rows with their (potentially) new heights
|
||||
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
|
||||
nsRect rowBounds = rowFrame->GetRect();
|
||||
nsRect rowVisualOverflow = rowFrame->GetVisualOverflowRect();
|
||||
|
||||
bool movedFrame = (rowBounds.y != yOrigin);
|
||||
nscoord rowHeight = (rowInfo[rowIndex].height > 0) ? rowInfo[rowIndex].height : 0;
|
||||
@ -755,6 +762,9 @@ nsTableRowGroupFrame::CalculateRowHeights(nsPresContext* aPresContext,
|
||||
|
||||
rowFrame->SetRect(nsRect(rowBounds.x, yOrigin, rowBounds.width,
|
||||
rowHeight));
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(rowFrame, rowBounds, rowVisualOverflow,
|
||||
false);
|
||||
}
|
||||
if (movedFrame) {
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
@ -798,6 +808,8 @@ nsTableRowGroupFrame::CollapseRowGroupIfNecessary(nscoord aYTotalOffset,
|
||||
}
|
||||
|
||||
nsRect groupRect = GetRect();
|
||||
nsRect oldGroupRect = groupRect;
|
||||
nsRect oldGroupVisualOverflow = GetVisualOverflowRect();
|
||||
|
||||
groupRect.height -= yGroupOffset;
|
||||
if (didCollapse) {
|
||||
@ -816,6 +828,9 @@ nsTableRowGroupFrame::CollapseRowGroupIfNecessary(nscoord aYTotalOffset,
|
||||
overflow.UnionAllWith(nsRect(0, 0, groupRect.width, groupRect.height));
|
||||
FinishAndStoreOverflow(overflow, nsSize(groupRect.width, groupRect.height));
|
||||
nsTableFrame::RePositionViews(this);
|
||||
nsTableFrame::InvalidateTableFrame(this, oldGroupRect, oldGroupVisualOverflow,
|
||||
false);
|
||||
|
||||
return yGroupOffset;
|
||||
}
|
||||
|
||||
@ -1052,6 +1067,10 @@ nsTableRowGroupFrame::SplitRowGroup(nsPresContext* aPresContext,
|
||||
rowReflowState.mFlags.mIsTopOfPage = isTopOfPage; // set top of page
|
||||
nsHTMLReflowMetrics rowMetrics;
|
||||
|
||||
// Get the old size before we reflow.
|
||||
nsRect oldRowRect = rowFrame->GetRect();
|
||||
nsRect oldRowVisualOverflow = rowFrame->GetVisualOverflowRect();
|
||||
|
||||
// Reflow the cell with the constrained height. A cell with rowspan >1 will get this
|
||||
// reflow later during SplitSpanningCells.
|
||||
rv = ReflowChild(rowFrame, aPresContext, rowMetrics, rowReflowState,
|
||||
@ -1061,6 +1080,10 @@ nsTableRowGroupFrame::SplitRowGroup(nsPresContext* aPresContext,
|
||||
rowFrame->DidReflow(aPresContext, nullptr, NS_FRAME_REFLOW_FINISHED);
|
||||
rowFrame->DidResize();
|
||||
|
||||
nsTableFrame::InvalidateTableFrame(rowFrame, oldRowRect,
|
||||
oldRowVisualOverflow,
|
||||
false);
|
||||
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
// The row frame is incomplete and all of the rowspan 1 cells' block frames split
|
||||
if ((rowMetrics.height <= rowReflowState.availableHeight) || isTopOfPage) {
|
||||
@ -1288,6 +1311,13 @@ nsTableRowGroupFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
aDesiredSize.UnionOverflowAreasWithDesiredBounds();
|
||||
|
||||
// If our parent is in initial reflow, it'll handle invalidating our
|
||||
// entire overflow rect.
|
||||
if (!(GetParent()->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
|
||||
nsSize(aDesiredSize.width, aDesiredSize.height) != mRect.Size()) {
|
||||
InvalidateFrame();
|
||||
}
|
||||
|
||||
FinishAndStoreOverflow(&aDesiredSize);
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
return rv;
|
||||
@ -1843,9 +1873,18 @@ nsTableRowGroupFrame::FrameCursorData::AppendFrame(nsIFrame* aFrame)
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowGroupFrame::InvalidateFrame()
|
||||
nsTableRowGroupFrame::InvalidateFrame(uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrame();
|
||||
nsTableFrame *tableFrame = nsTableFrame::GetTableFrame(this);
|
||||
tableFrame->InvalidateFrame();
|
||||
nsIFrame::InvalidateFrame(aDisplayItemKey);
|
||||
GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowGroupFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
|
||||
{
|
||||
nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
|
||||
// If we have filters applied that would affects our bounds, then
|
||||
// we get an inactive layer created and this is computed
|
||||
// within FrameLayerBuilder
|
||||
GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
|
||||
}
|
||||
|
@ -325,7 +325,9 @@ public:
|
||||
|
||||
virtual nsILineIterator* GetLineIterator() { return this; }
|
||||
|
||||
virtual void InvalidateFrame();
|
||||
virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) MOZ_OVERRIDE;
|
||||
virtual void InvalidateFrameForRemoval() MOZ_OVERRIDE { InvalidateFrameSubtree(); }
|
||||
|
||||
protected:
|
||||
nsTableRowGroupFrame(nsStyleContext* aContext);
|
||||
|
Loading…
Reference in New Issue
Block a user