bug 558574 - fix issues with table footer placement and missed page breaks inside of row groups r=roc

This commit is contained in:
Bernd 2010-05-13 16:15:49 +02:00
parent 5abba25dc5
commit 5b3485bfc6
4 changed files with 82 additions and 32 deletions

View File

@ -286,20 +286,25 @@ IsRepeatedFrame(nsIFrame* kidFrame)
}
PRBool
nsTableFrame::PageBreakAfter(nsIFrame& aSourceFrame,
nsTableFrame::PageBreakAfter(nsIFrame* aSourceFrame,
nsIFrame* aNextFrame)
{
const nsStyleDisplay* display = aSourceFrame.GetStyleDisplay();
const nsStyleDisplay* display = aSourceFrame->GetStyleDisplay();
nsTableRowGroupFrame* prevRg = do_QueryFrame(aSourceFrame);
// don't allow a page break after a repeated element ...
if (display->mBreakAfter && !IsRepeatedFrame(&aSourceFrame)) {
if (display->mBreakAfter || (prevRg && prevRg->HasInternalBreakAfter()) &&
!IsRepeatedFrame(aSourceFrame)) {
return !(aNextFrame && IsRepeatedFrame(aNextFrame)); // or before
}
if (aNextFrame) {
display = aNextFrame->GetStyleDisplay();
// don't allow a page break before a repeated element ...
if (display->mBreakBefore && !IsRepeatedFrame(aNextFrame)) {
return !IsRepeatedFrame(&aSourceFrame); // or after
nsTableRowGroupFrame* nextRg = do_QueryFrame(aNextFrame);
if (display->mBreakBefore ||
(nextRg && nextRg->HasInternalBreakBefore()) &&
!IsRepeatedFrame(aNextFrame)) {
return !IsRepeatedFrame(aSourceFrame); // or after
}
}
return PR_FALSE;
@ -2613,6 +2618,34 @@ nsTableFrame::SetupHeaderFooterChild(const nsTableReflowState& aReflowState,
return NS_OK;
}
void
nsTableFrame::PlaceRepeatedFooter(nsTableReflowState& aReflowState,
nsTableRowGroupFrame *aTfoot,
nscoord aFooterHeight)
{
nsPresContext* presContext = PresContext();
nsSize kidAvailSize(aReflowState.availSize);
kidAvailSize.height = aFooterHeight;
nsHTMLReflowState footerReflowState(presContext,
aReflowState.reflowState,
aTfoot, kidAvailSize,
-1, -1, PR_FALSE);
InitChildReflowState(footerReflowState);
aReflowState.y += GetCellSpacingY();
nsRect origTfootRect = aTfoot->GetRect();
nsRect origTfootOverflowRect = aTfoot->GetOverflowRect();
nsReflowStatus footerStatus;
nsHTMLReflowMetrics desiredSize;
desiredSize.width = desiredSize.height = 0;
ReflowChild(aTfoot, presContext, desiredSize, footerReflowState,
aReflowState.x, aReflowState.y,
NS_FRAME_INVALIDATE_ON_MOVE, footerStatus);
PlaceChild(aReflowState, aTfoot, desiredSize, origTfootRect,
origTfootOverflowRect);
}
// Reflow the children based on the avail size and reason in aReflowState
// update aReflowMetrics a aStatus
NS_METHOD
@ -2630,7 +2663,8 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
nsPresContext* presContext = PresContext();
// XXXldb Should we be checking constrained height instead?
PRBool isPaginated = presContext->IsPaginated();
PRBool isPaginated = presContext->IsPaginated() &&
NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height;
aOverflowArea = nsRect (0, 0, 0, 0);
@ -2665,7 +2699,8 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
return rv;
}
}
// if the child is a tbody in paginated mode reduce the height by a repeated footer
PRBool allowRepeatedFooter = PR_FALSE;
for (PRUint32 childX = 0; childX < rowGroups.Length(); childX++) {
nsIFrame* kidFrame = rowGroups[childX];
// Get the frame state bits
@ -2677,13 +2712,15 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
NS_FRAME_CONTAINS_RELATIVE_HEIGHT)))) {
if (pageBreak) {
PushChildren(rowGroups, childX);
if (allowRepeatedFooter) {
PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
}
aStatus = NS_FRAME_NOT_COMPLETE;
break;
}
nsSize kidAvailSize(aReflowState.availSize);
// if the child is a tbody in paginated mode reduce the height by a repeated footer
PRBool allowRepeatedFooter = PR_FALSE;
allowRepeatedFooter = PR_FALSE;
if (isPaginated && (NS_UNCONSTRAINEDSIZE != kidAvailSize.height)) {
nsTableRowGroupFrame* kidRG =
static_cast<nsTableRowGroupFrame*>(kidFrame);
@ -2754,6 +2791,9 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
if (nextRowGroupFrame) {
PlaceChild(aReflowState, kidFrame, desiredSize, oldKidRect,
oldKidOverflowRect);
if (allowRepeatedFooter) {
PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
}
aStatus = NS_FRAME_NOT_COMPLETE;
PushChildren(rowGroups, childX + 1);
aLastChildReflowed = kidFrame;
@ -2763,7 +2803,9 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
}
else { // we are not on top, push this rowgroup onto the next page
if (prevKidFrame) { // we had a rowgroup before so push this
// XXXroc shouldn't we add a repeated footer here?
if (allowRepeatedFooter) {
PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
}
aStatus = NS_FRAME_NOT_COMPLETE;
PushChildren(rowGroups, childX);
aLastChildReflowed = prevKidFrame;
@ -2780,7 +2822,7 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight)) {
nsIFrame* nextKid =
(childX + 1 < rowGroups.Length()) ? rowGroups[childX + 1] : nsnull;
pageBreak = PageBreakAfter(*kidFrame, nextKid);
pageBreak = PageBreakAfter(kidFrame, nextKid);
}
// Place the child
@ -2823,23 +2865,7 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
PushChildren(rowGroups, childX + 1);
}
if (allowRepeatedFooter) {
kidAvailSize.height = footerHeight;
nsHTMLReflowState footerReflowState(presContext,
aReflowState.reflowState,
tfoot, kidAvailSize,
-1, -1, PR_FALSE);
InitChildReflowState(footerReflowState);
aReflowState.y += cellSpacingY;
nsRect origTfootRect = tfoot->GetRect();
nsRect origTfootOverflowRect = tfoot->GetOverflowRect();
nsReflowStatus footerStatus;
rv = ReflowChild(tfoot, presContext, desiredSize, footerReflowState,
aReflowState.x, aReflowState.y,
NS_FRAME_INVALIDATE_ON_MOVE, footerStatus);
PlaceChild(aReflowState, tfoot, desiredSize, origTfootRect,
origTfootOverflowRect);
PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
}
break;
}

View File

@ -177,7 +177,7 @@ public:
static void RePositionViews(nsIFrame* aFrame);
static PRBool PageBreakAfter(nsIFrame& aSourceFrame,
static PRBool PageBreakAfter(nsIFrame* aSourceFrame,
nsIFrame* aNextFrame);
nsPoint GetFirstSectionOrigin(const nsHTMLReflowState& aReflowState) const;
@ -607,6 +607,9 @@ protected:
nsHTMLReflowMetrics& aKidDesiredSize,
const nsRect& aOriginalKidRect,
const nsRect& aOriginalKidOverflowRect);
void PlaceRepeatedFooter(nsTableReflowState& aReflowState,
nsTableRowGroupFrame *aTfoot,
nscoord aFooterHeight);
nsIFrame* GetFirstBodyRowGroupFrame();
public:

View File

@ -363,7 +363,8 @@ nsTableRowGroupFrame::ReflowChildren(nsPresContext* aPresContext,
// XXXldb Should we really be checking this rather than available height?
// (Think about multi-column layout!)
PRBool isPaginated = aPresContext->IsPaginated();
PRBool isPaginated = aPresContext->IsPaginated() &&
NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height;
PRBool haveRow = PR_FALSE;
PRBool reflowAllKids = aReflowState.reflowState.ShouldReflowAllKids() ||
@ -459,7 +460,7 @@ nsTableRowGroupFrame::ReflowChildren(nsPresContext* aPresContext,
if (isPaginated && aPageBreakBeforeEnd && !*aPageBreakBeforeEnd) {
nsTableRowFrame* nextRow = rowFrame->GetNextRow();
if (nextRow) {
*aPageBreakBeforeEnd = nsTableFrame::PageBreakAfter(*kidFrame, nextRow);
*aPageBreakBeforeEnd = nsTableFrame::PageBreakAfter(kidFrame, nextRow);
}
}
} else {
@ -1268,7 +1269,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsPresContext* aPresContext,
prevRowFrame = rowFrame;
// see if there is a page break after the row
nsTableRowFrame* nextRow = rowFrame->GetNextRow();
if (nextRow && nsTableFrame::PageBreakAfter(*rowFrame, nextRow)) {
if (nextRow && nsTableFrame::PageBreakAfter(rowFrame, nextRow)) {
PushChildren(aPresContext, nextRow, rowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
break;
@ -1569,7 +1570,25 @@ nsTableRowGroupFrame::GetType() const
return nsGkAtoms::tableRowGroupFrame;
}
/** find page break before the first row **/
PRBool
nsTableRowGroupFrame::HasInternalBreakBefore() const
{
nsIFrame* firstChild = mFrames.FirstChild();
if (!firstChild)
return PR_FALSE;
return firstChild->GetStyleDisplay()->mBreakBefore;
}
/** find page break after the last row **/
PRBool
nsTableRowGroupFrame::HasInternalBreakAfter() const
{
nsIFrame* lastChild = mFrames.LastChild();
if (!lastChild)
return PR_FALSE;
return lastChild->GetStyleDisplay()->mBreakAfter;
}
/* ----- global methods ----- */
nsIFrame*

View File

@ -436,6 +436,8 @@ public:
void SetRepeatable(PRBool aRepeatable);
PRBool HasStyleHeight() const;
void SetHasStyleHeight(PRBool aValue);
PRBool HasInternalBreakBefore() const;
PRBool HasInternalBreakAfter() const;
};