bug 24000 - implement page-break-before/after:always using new nsPageBreakFrame. Tables handle page breaks internally. a=asa, sr=attinasi, r=alexsavulov

This commit is contained in:
karnaze%netscape.com 2002-03-17 21:35:08 +00:00
Родитель 057a05b72e
Коммит 773d422073
40 изменённых файлов: 946 добавлений и 172 удалений

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

@ -783,7 +783,9 @@ static const PropertyCheckData DisplayCheckProperties[] = {
CHECKDATA_PROP(nsCSSDisplay, mPosition, CHECKDATA_VALUE, PR_FALSE),
CHECKDATA_PROP(nsCSSDisplay, mFloat, CHECKDATA_VALUE, PR_FALSE),
CHECKDATA_PROP(nsCSSDisplay, mClear, CHECKDATA_VALUE, PR_FALSE),
CHECKDATA_PROP(nsCSSDisplay, mOverflow, CHECKDATA_VALUE, PR_FALSE)
CHECKDATA_PROP(nsCSSDisplay, mOverflow, CHECKDATA_VALUE, PR_FALSE),
CHECKDATA_PROP(nsCSSDisplay, mBreakBefore, CHECKDATA_VALUE, PR_FALSE), // temp fix for bug 2400
CHECKDATA_PROP(nsCSSDisplay, mBreakAfter, CHECKDATA_VALUE, PR_FALSE) // temp fix for bug 2400
};
static const PropertyCheckData VisibilityCheckProperties[] = {
@ -2824,6 +2826,15 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct, const nsCSSStruct& a
display->mBreakType = parentDisplay->mBreakType;
}
// temp fix for bug 24000
if (eCSSUnit_Enumerated == displayData.mBreakBefore.GetUnit()) {
display->mBreakBefore = (NS_STYLE_PAGE_BREAK_ALWAYS == displayData.mBreakBefore.GetIntValue());
}
if (eCSSUnit_Enumerated == displayData.mBreakAfter.GetUnit()) {
display->mBreakAfter = (NS_STYLE_PAGE_BREAK_ALWAYS == displayData.mBreakAfter.GetIntValue());
}
// end temp fix
// float: enum, none, inherit
if (eCSSUnit_Enumerated == displayData.mFloat.GetUnit()) {
display->mFloats = displayData.mFloat.GetIntValue();

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

@ -379,6 +379,10 @@ nsCSSDisplay::nsCSSDisplay(const nsCSSDisplay& aCopy)
mPosition(aCopy.mPosition),
mFloat(aCopy.mFloat),
mClear(aCopy.mClear),
// temp fix for bug 24000
mBreakBefore(aCopy.mBreakBefore),
mBreakAfter(aCopy.mBreakAfter),
// end temp
mClip(nsnull),
mOverflow(aCopy.mOverflow),
mVisibility(aCopy.mVisibility),
@ -1794,18 +1798,26 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_ENSURE(Breaks) {
switch (aProperty) {
case eCSSProperty_orphans: theBreaks->mOrphans = aValue; break;
case eCSSProperty_widows: theBreaks->mWidows = aValue; break;
case eCSSProperty_page: theBreaks->mPage = aValue; break;
case eCSSProperty_page_break_after: theBreaks->mPageBreakAfter = aValue; break;
case eCSSProperty_page_break_before: theBreaks->mPageBreakBefore = aValue; break;
case eCSSProperty_page_break_inside: theBreaks->mPageBreakInside = aValue; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_ENSURE(Display) {
switch (aProperty) {
case eCSSProperty_page_break_after: theDisplay->mBreakAfter = aValue; break;
case eCSSProperty_page_break_before: theDisplay->mBreakBefore = aValue; break;
case eCSSProperty_page_break_inside: break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
@ -2739,10 +2751,7 @@ nsCSSDeclaration::SetValueImportant(nsCSSProperty aProperty)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_VARONSTACK_GET(Breaks);
if (nsnull != theBreaks) {
CSS_ENSURE_IMPORTANT(Breaks) {
@ -2750,9 +2759,22 @@ nsCSSDeclaration::SetValueImportant(nsCSSProperty aProperty)
CSS_CASE_IMPORTANT(eCSSProperty_orphans, Breaks, mOrphans);
CSS_CASE_IMPORTANT(eCSSProperty_widows, Breaks, mWidows);
CSS_CASE_IMPORTANT(eCSSProperty_page, Breaks, mPage);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_after, Breaks, mPageBreakAfter);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_before, Breaks, mPageBreakBefore);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_inside, Breaks, mPageBreakInside);
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_VARONSTACK_GET(Display);
if (theDisplay) {
CSS_ENSURE_IMPORTANT(Display) {
switch (aProperty) {
CSS_CASE_IMPORTANT(eCSSProperty_page_break_after, Display, mBreakAfter);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_before, Display, mBreakBefore);
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
@ -3593,24 +3615,30 @@ nsCSSDeclaration::RemoveProperty(nsCSSProperty aProperty)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_CHECK(Breaks) {
switch (aProperty) {
case eCSSProperty_orphans: theBreaks->mOrphans.Reset(); break;
case eCSSProperty_widows: theBreaks->mWidows.Reset(); break;
case eCSSProperty_page: theBreaks->mPage.Reset(); break;
case eCSSProperty_page_break_after: theBreaks->mPageBreakAfter.Reset(); break;
case eCSSProperty_page_break_before: theBreaks->mPageBreakBefore.Reset(); break;
case eCSSProperty_page_break_inside: theBreaks->mPageBreakInside.Reset(); break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_CHECK(Display) {
switch (aProperty) {
case eCSSProperty_page_break_after: theDisplay->mBreakAfter.Reset(); break;
case eCSSProperty_page_break_before: theDisplay->mBreakBefore.Reset(); break;
case eCSSProperty_page_break_inside: break;
}
}
break;
}
// nsCSSPage
case eCSSProperty_marks:
case eCSSProperty_size_width:
@ -4432,19 +4460,31 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_VARONSTACK_GET(Breaks);
if (nsnull != theBreaks) {
switch (aProperty) {
case eCSSProperty_orphans: aValue = theBreaks->mOrphans; break;
case eCSSProperty_widows: aValue = theBreaks->mWidows; break;
case eCSSProperty_page: aValue = theBreaks->mPage; break;
case eCSSProperty_page_break_after: aValue = theBreaks->mPageBreakAfter; break;
case eCSSProperty_page_break_before: aValue = theBreaks->mPageBreakBefore; break;
case eCSSProperty_page_break_inside: aValue = theBreaks->mPageBreakInside; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
else {
aValue.Reset();
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_VARONSTACK_GET(Display);
if (theDisplay) {
switch (aProperty) {
case eCSSProperty_page_break_inside: aValue.Reset(); break;
case eCSSProperty_page_break_after: aValue = theDisplay->mBreakAfter; break;
case eCSSProperty_page_break_before: aValue = theDisplay->mBreakBefore; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}

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

@ -240,6 +240,10 @@ struct nsCSSDisplay : public nsCSSStruct {
// in nsCSSDeclaration objects but because it's needed on the
// stack when the struct is used in WalkRuleTree.
nsCSSValue mLang;
// temp fix for bug 24000
nsCSSValue mBreakBefore;
nsCSSValue mBreakAfter;
// end temp fix
};
struct nsCSSMargin : public nsCSSStruct {

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

@ -379,6 +379,10 @@ nsCSSDisplay::nsCSSDisplay(const nsCSSDisplay& aCopy)
mPosition(aCopy.mPosition),
mFloat(aCopy.mFloat),
mClear(aCopy.mClear),
// temp fix for bug 24000
mBreakBefore(aCopy.mBreakBefore),
mBreakAfter(aCopy.mBreakAfter),
// end temp
mClip(nsnull),
mOverflow(aCopy.mOverflow),
mVisibility(aCopy.mVisibility),
@ -1794,18 +1798,26 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_ENSURE(Breaks) {
switch (aProperty) {
case eCSSProperty_orphans: theBreaks->mOrphans = aValue; break;
case eCSSProperty_widows: theBreaks->mWidows = aValue; break;
case eCSSProperty_page: theBreaks->mPage = aValue; break;
case eCSSProperty_page_break_after: theBreaks->mPageBreakAfter = aValue; break;
case eCSSProperty_page_break_before: theBreaks->mPageBreakBefore = aValue; break;
case eCSSProperty_page_break_inside: theBreaks->mPageBreakInside = aValue; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_ENSURE(Display) {
switch (aProperty) {
case eCSSProperty_page_break_after: theDisplay->mBreakAfter = aValue; break;
case eCSSProperty_page_break_before: theDisplay->mBreakBefore = aValue; break;
case eCSSProperty_page_break_inside: break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
@ -2739,10 +2751,7 @@ nsCSSDeclaration::SetValueImportant(nsCSSProperty aProperty)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_VARONSTACK_GET(Breaks);
if (nsnull != theBreaks) {
CSS_ENSURE_IMPORTANT(Breaks) {
@ -2750,9 +2759,22 @@ nsCSSDeclaration::SetValueImportant(nsCSSProperty aProperty)
CSS_CASE_IMPORTANT(eCSSProperty_orphans, Breaks, mOrphans);
CSS_CASE_IMPORTANT(eCSSProperty_widows, Breaks, mWidows);
CSS_CASE_IMPORTANT(eCSSProperty_page, Breaks, mPage);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_after, Breaks, mPageBreakAfter);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_before, Breaks, mPageBreakBefore);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_inside, Breaks, mPageBreakInside);
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_VARONSTACK_GET(Display);
if (theDisplay) {
CSS_ENSURE_IMPORTANT(Display) {
switch (aProperty) {
CSS_CASE_IMPORTANT(eCSSProperty_page_break_after, Display, mBreakAfter);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_before, Display, mBreakBefore);
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
@ -3593,24 +3615,30 @@ nsCSSDeclaration::RemoveProperty(nsCSSProperty aProperty)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_CHECK(Breaks) {
switch (aProperty) {
case eCSSProperty_orphans: theBreaks->mOrphans.Reset(); break;
case eCSSProperty_widows: theBreaks->mWidows.Reset(); break;
case eCSSProperty_page: theBreaks->mPage.Reset(); break;
case eCSSProperty_page_break_after: theBreaks->mPageBreakAfter.Reset(); break;
case eCSSProperty_page_break_before: theBreaks->mPageBreakBefore.Reset(); break;
case eCSSProperty_page_break_inside: theBreaks->mPageBreakInside.Reset(); break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_CHECK(Display) {
switch (aProperty) {
case eCSSProperty_page_break_after: theDisplay->mBreakAfter.Reset(); break;
case eCSSProperty_page_break_before: theDisplay->mBreakBefore.Reset(); break;
case eCSSProperty_page_break_inside: break;
}
}
break;
}
// nsCSSPage
case eCSSProperty_marks:
case eCSSProperty_size_width:
@ -4432,19 +4460,31 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_VARONSTACK_GET(Breaks);
if (nsnull != theBreaks) {
switch (aProperty) {
case eCSSProperty_orphans: aValue = theBreaks->mOrphans; break;
case eCSSProperty_widows: aValue = theBreaks->mWidows; break;
case eCSSProperty_page: aValue = theBreaks->mPage; break;
case eCSSProperty_page_break_after: aValue = theBreaks->mPageBreakAfter; break;
case eCSSProperty_page_break_before: aValue = theBreaks->mPageBreakBefore; break;
case eCSSProperty_page_break_inside: aValue = theBreaks->mPageBreakInside; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
else {
aValue.Reset();
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_VARONSTACK_GET(Display);
if (theDisplay) {
switch (aProperty) {
case eCSSProperty_page_break_inside: aValue.Reset(); break;
case eCSSProperty_page_break_after: aValue = theDisplay->mBreakAfter; break;
case eCSSProperty_page_break_before: aValue = theDisplay->mBreakBefore; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}

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

@ -240,6 +240,10 @@ struct nsCSSDisplay : public nsCSSStruct {
// in nsCSSDeclaration objects but because it's needed on the
// stack when the struct is used in WalkRuleTree.
nsCSSValue mLang;
// temp fix for bug 24000
nsCSSValue mBreakBefore;
nsCSSValue mBreakAfter;
// end temp fix
};
struct nsCSSMargin : public nsCSSStruct {

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

@ -2306,6 +2306,13 @@ MapDisplayForDeclaration(nsCSSDeclaration* aDecl, const nsStyleStructID& aID, ns
if (aDisplay.mClear.GetUnit() == eCSSUnit_Null && ourDisplay->mClear.GetUnit() != eCSSUnit_Null)
aDisplay.mClear = ourDisplay->mClear;
// temp fix for bug 24000
if (aDisplay.mBreakBefore.GetUnit() == eCSSUnit_Null && ourDisplay->mBreakBefore.GetUnit() != eCSSUnit_Null)
aDisplay.mBreakBefore = ourDisplay->mBreakBefore;
if (aDisplay.mBreakAfter.GetUnit() == eCSSUnit_Null && ourDisplay->mBreakAfter.GetUnit() != eCSSUnit_Null)
aDisplay.mBreakAfter = ourDisplay->mBreakAfter;
// end temp fix
// float: enum, none, inherit
if (aDisplay.mFloat.GetUnit() == eCSSUnit_Null && ourDisplay->mFloat.GetUnit() != eCSSUnit_Null)
aDisplay.mFloat = ourDisplay->mFloat;

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

@ -99,6 +99,7 @@ CSS_KEY(-moz-inline-grid, _moz_inline_grid)
CSS_KEY(-moz-grid-group, _moz_grid_group)
CSS_KEY(-moz-grid-line, _moz_grid_line)
CSS_KEY(-moz-groupbox, _moz_groupbox)
CSS_KEY(-moz-page-break, _moz_page_break)
CSS_KEY(-moz-popup, _moz_popup)
CSS_KEY(-moz-stack, _moz_stack)
CSS_KEY(-moz-inline-stack, _moz_inline_stack)

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

@ -88,6 +88,7 @@ LAYOUT_ATOM(canvasPseudo, ":canvas")
LAYOUT_ATOM(commentTagName, "__moz_comment")
LAYOUT_ATOM(dummyOptionPseudo, ":-moz-dummy-option")
LAYOUT_ATOM(textTagName, "__moz_text")
LAYOUT_ATOM(pageBreakPseudo, ":-moz-pagebreak")
LAYOUT_ATOM(pagePseudo, ":-moz-page")
LAYOUT_ATOM(pageContentPseudo, ":-moz-pagecontent")
LAYOUT_ATOM(pageSequencePseudo, ":-moz-page-sequence")
@ -116,6 +117,7 @@ LAYOUT_ATOM(lineFrame, "LineFrame")
LAYOUT_ATOM(listControlFrame,"ListControlFrame")
LAYOUT_ATOM(objectFrame, "ObjectFrame")
LAYOUT_ATOM(pageFrame, "PageFrame")
LAYOUT_ATOM(pageBreakFrame, "PageBreakFrame")
LAYOUT_ATOM(pageContentFrame, "PageContentFrame")
LAYOUT_ATOM(placeholderFrame, "PlaceholderFrame")
LAYOUT_ATOM(positionedInlineFrame, "PositionedInlineFrame")

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

@ -409,6 +409,7 @@ const PRInt32 nsCSSProps::kDisplayKTable[] = {
eCSSKeyword__moz_bulletinboard, NS_STYLE_DISPLAY_BULLETINBOARD,
eCSSKeyword__moz_popup, NS_STYLE_DISPLAY_POPUP,
eCSSKeyword__moz_groupbox, NS_STYLE_DISPLAY_GROUPBOX,
eCSSKeyword__moz_page_break, NS_STYLE_DISPLAY_PAGE_BREAK,
-1,-1
};

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

@ -2281,6 +2281,9 @@ nsCSSFrameConstructor::GetParentFrame(nsIPresShell* aPresShell,
}
// Construct the outer, inner table frames and the children frames for the table.
// XXX Page break frames for pseudo table frames are not constructed to avoid the risk
// associated with revising the pseudo frame mechanism. The long term solution
// of having frames handle page-break-before/after will solve the problem.
nsresult
nsCSSFrameConstructor::ConstructTableFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
@ -2923,10 +2926,27 @@ nsCSSFrameConstructor::TableProcessChild(nsIPresShell* aPresShell,
switch (styleDisplay->mDisplay) {
case NS_STYLE_DISPLAY_TABLE:
nsIFrame* innerTableFrame;
rv = ConstructTableFrame(aPresShell, aPresContext, aState, aChildContent, aParentFrame,
childStyleContext, aTableCreator, PR_FALSE, aChildItems,
childFrame, innerTableFrame, isPseudoParent);
{
PRBool pageBreakAfter = PR_FALSE;
PRBool paginated;
aPresContext->IsPaginated(&paginated);
if (paginated) {
// See if there is a page break before, if so construct one. Also see if there is one after
pageBreakAfter = PageBreakBefore(aPresShell, aPresContext, aState, aChildContent,
aParentFrame, childStyleContext, aChildItems);
}
// construct the table frame
nsIFrame* innerTableFrame;
rv = ConstructTableFrame(aPresShell, aPresContext, aState, aChildContent, aParentFrame,
childStyleContext, aTableCreator, PR_FALSE, aChildItems,
childFrame, innerTableFrame, isPseudoParent);
if (NS_SUCCEEDED(rv) && pageBreakAfter) {
// Construct the page break after
ConstructPageBreakFrame(aPresShell, aPresContext, aState, aChildContent,
aParentFrame, childStyleContext, aChildItems);
}
}
break;
case NS_STYLE_DISPLAY_TABLE_CAPTION:
@ -6975,8 +6995,56 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsIPresShell* aPresShell,
}
#endif // MOZ_SVG
PRBool
nsCSSFrameConstructor::PageBreakBefore(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems)
{
const nsStyleDisplay* display = (const nsStyleDisplay*)
aStyleContext->GetStyleData(eStyleStruct_Display);
// See if page-break-before is set for all elements except row groups, rows, cells
// (these are handled internally by tables) and construct a page break frame if so.
if (display && ((NS_STYLE_DISPLAY_TABLE == display->mDisplay) ||
(!IsTableRelated(display->mDisplay, PR_TRUE)))) {
if (display->mBreakBefore) {
ConstructPageBreakFrame(aPresShell, aPresContext, aState, aContent,
aParentFrame, aStyleContext, aFrameItems);
}
return display->mBreakAfter;
}
return PR_FALSE;
}
nsresult
nsCSSFrameConstructor::ConstructFrame(nsIPresShell* aPresShell,
nsCSSFrameConstructor::ConstructPageBreakFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems)
{
nsCOMPtr<nsIStyleContext> pseudoStyle;
aPresContext->ResolvePseudoStyleContextFor(nsnull, nsLayoutAtoms::pageBreakPseudo,
aStyleContext, PR_FALSE,
getter_AddRefs(pseudoStyle));
nsIFrame* pageBreakFrame;
nsresult rv = NS_NewPageBreakFrame(aPresShell, &pageBreakFrame);
if (NS_SUCCEEDED(rv)) {
InitAndRestoreFrame(aPresContext, aState, aContent, aParentFrame,
pseudoStyle, nsnull, pageBreakFrame);
aFrameItems.AddChild(pageBreakFrame);
}
return rv;
}
nsresult
nsCSSFrameConstructor::ConstructFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
@ -7006,20 +7074,27 @@ nsCSSFrameConstructor::ConstructFrame(nsIPresShell* aPresShell,
rv = ResolveStyleContext(aPresContext, aParentFrame, aContent,
getter_AddRefs(styleContext));
if (NS_SUCCEEDED(rv)) {
if (NS_SUCCEEDED(rv)) {
PRInt32 nameSpaceID;
aContent->GetNameSpaceID(nameSpaceID);
rv = ConstructFrameInternal(aPresShell,
aPresContext,
aState,
aContent,
aParentFrame,
tag,
nameSpaceID,
styleContext,
aFrameItems,
PR_FALSE);
PRBool pageBreakAfter = PR_FALSE;
PRBool paginated;
aPresContext->IsPaginated(&paginated);
if (paginated) {
// See if there is a page break before, if so construct one. Also see if there is one after
pageBreakAfter = PageBreakBefore(aPresShell, aPresContext, aState, aContent,
aParentFrame, styleContext, aFrameItems);
}
// construct the frame
rv = ConstructFrameInternal(aPresShell, aPresContext, aState, aContent, aParentFrame,
tag, nameSpaceID, styleContext, aFrameItems, PR_FALSE);
if (NS_SUCCEEDED(rv) && pageBreakAfter) {
// Construct the page break after
ConstructPageBreakFrame(aPresShell, aPresContext, aState, aContent,
aParentFrame, styleContext, aFrameItems);
}
}
return rv;

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

@ -535,6 +535,25 @@ protected:
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems);
nsresult ConstructPageBreakFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems);
// Construct a page break frame if page-break-before:always is set in aStyleContext
// and add it to aFrameItems. Return true if page-break-after:always is set on aStyleContext.
// Don't do this for row groups, rows or cell, because tables handle those internally.
PRBool PageBreakBefore(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems);
nsresult ConstructHTMLFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,

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

@ -88,6 +88,7 @@ LAYOUT_ATOM(canvasPseudo, ":canvas")
LAYOUT_ATOM(commentTagName, "__moz_comment")
LAYOUT_ATOM(dummyOptionPseudo, ":-moz-dummy-option")
LAYOUT_ATOM(textTagName, "__moz_text")
LAYOUT_ATOM(pageBreakPseudo, ":-moz-pagebreak")
LAYOUT_ATOM(pagePseudo, ":-moz-page")
LAYOUT_ATOM(pageContentPseudo, ":-moz-pagecontent")
LAYOUT_ATOM(pageSequencePseudo, ":-moz-page-sequence")
@ -116,6 +117,7 @@ LAYOUT_ATOM(lineFrame, "LineFrame")
LAYOUT_ATOM(listControlFrame,"ListControlFrame")
LAYOUT_ATOM(objectFrame, "ObjectFrame")
LAYOUT_ATOM(pageFrame, "PageFrame")
LAYOUT_ATOM(pageBreakFrame, "PageBreakFrame")
LAYOUT_ATOM(pageContentFrame, "PageContentFrame")
LAYOUT_ATOM(placeholderFrame, "PlaceholderFrame")
LAYOUT_ATOM(positionedInlineFrame, "PositionedInlineFrame")

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

@ -336,6 +336,7 @@
#define NS_STYLE_DISPLAY_BULLETINBOARD 27
#define NS_STYLE_DISPLAY_POPUP 28
#define NS_STYLE_DISPLAY_GROUPBOX 29
#define NS_STYLE_DISPLAY_PAGE_BREAK 30
// See nsStyleDisplay
#define NS_STYLE_FLOAT_NONE 0

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

@ -336,6 +336,7 @@
#define NS_STYLE_DISPLAY_BULLETINBOARD 27
#define NS_STYLE_DISPLAY_POPUP 28
#define NS_STYLE_DISPLAY_GROUPBOX 29
#define NS_STYLE_DISPLAY_PAGE_BREAK 30
// See nsStyleDisplay
#define NS_STYLE_FLOAT_NONE 0

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

@ -170,6 +170,7 @@ extern nsresult NS_NewScrollFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewPageContentFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewFirstLetterFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
extern nsresult NS_NewFirstLineFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);

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

@ -759,3 +759,90 @@ nsPageFrame::DrawBackground(nsIPresContext* aPresContext,
}
}
nsresult
NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aPresShell && aNewFrame, "null PresShell or OUT ptr");
#ifdef DEBUG
//check that we are only creating page break frames when printing
nsCOMPtr<nsIPresContext> presContext;
aPresShell->GetPresContext(getter_AddRefs(presContext));
PRBool isPaginated;
presContext->IsPaginated(&isPaginated);
NS_ASSERTION(isPaginated, "created a page break frame while not printing");
#endif
nsPageBreakFrame* it = new (aPresShell) nsPageBreakFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aNewFrame = it;
return NS_OK;
}
nsPageBreakFrame::nsPageBreakFrame()
: mHaveReflowed(PR_FALSE)
{
}
nsPageBreakFrame::~nsPageBreakFrame()
{
}
void
nsPageBreakFrame::GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize)
{
NS_PRECONDITION(aPresContext, "null pres context");
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSToCoordRound(p2t);
aDesiredSize.width = onePixel;
if (mHaveReflowed) {
// If blocks reflow us a 2nd time trying to put us on a new page, then return
// a desired height of 0 to avoid an extra page break.
aDesiredSize.height = 0;
}
else {
aDesiredSize.height = aReflowState.availableHeight;
// round the height down to the nearest pixel
aDesiredSize.height -= aDesiredSize.height % onePixel;
}
if (aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = onePixel;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aDesiredSize.ascent = 0;
aDesiredSize.descent = 0;
}
nsresult
nsPageBreakFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
NS_PRECONDITION(aPresContext, "null pres context");
DO_GLOBAL_REFLOW_COUNT("nsTableFrame", aReflowState.reason);
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
aStatus = NS_FRAME_COMPLETE;
GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
mHaveReflowed = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsPageBreakFrame::GetFrameType(nsIAtom** aType) const
{
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
*aType = nsLayoutAtoms::pageBreakFrame;
NS_ADDREF(*aType);
return NS_OK;
}

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

@ -39,6 +39,7 @@
#include "nsContainerFrame.h"
#include "nsIPrintSettings.h"
#include "nsLeafFrame.h"
class nsSharedPageData;
@ -152,5 +153,28 @@ private:
const nsRect& aDirtyRect);
};
class nsPageBreakFrame : public nsLeafFrame {
nsPageBreakFrame();
~nsPageBreakFrame();
NS_IMETHOD Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
protected:
virtual void GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize);
PRBool mHaveReflowed;
friend nsresult NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
};
#endif /* nsPageFrame_h___ */

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

@ -170,6 +170,7 @@ extern nsresult NS_NewScrollFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewPageContentFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsIFrame** aResult);
extern nsresult NS_NewFirstLetterFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
extern nsresult NS_NewFirstLineFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);

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

@ -759,3 +759,90 @@ nsPageFrame::DrawBackground(nsIPresContext* aPresContext,
}
}
nsresult
NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
{
NS_PRECONDITION(aPresShell && aNewFrame, "null PresShell or OUT ptr");
#ifdef DEBUG
//check that we are only creating page break frames when printing
nsCOMPtr<nsIPresContext> presContext;
aPresShell->GetPresContext(getter_AddRefs(presContext));
PRBool isPaginated;
presContext->IsPaginated(&isPaginated);
NS_ASSERTION(isPaginated, "created a page break frame while not printing");
#endif
nsPageBreakFrame* it = new (aPresShell) nsPageBreakFrame;
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aNewFrame = it;
return NS_OK;
}
nsPageBreakFrame::nsPageBreakFrame()
: mHaveReflowed(PR_FALSE)
{
}
nsPageBreakFrame::~nsPageBreakFrame()
{
}
void
nsPageBreakFrame::GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize)
{
NS_PRECONDITION(aPresContext, "null pres context");
float p2t;
aPresContext->GetScaledPixelsToTwips(&p2t);
nscoord onePixel = NSToCoordRound(p2t);
aDesiredSize.width = onePixel;
if (mHaveReflowed) {
// If blocks reflow us a 2nd time trying to put us on a new page, then return
// a desired height of 0 to avoid an extra page break.
aDesiredSize.height = 0;
}
else {
aDesiredSize.height = aReflowState.availableHeight;
// round the height down to the nearest pixel
aDesiredSize.height -= aDesiredSize.height % onePixel;
}
if (aDesiredSize.maxElementSize) {
aDesiredSize.maxElementSize->width = onePixel;
aDesiredSize.maxElementSize->height = aDesiredSize.height;
}
aDesiredSize.ascent = 0;
aDesiredSize.descent = 0;
}
nsresult
nsPageBreakFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
NS_PRECONDITION(aPresContext, "null pres context");
DO_GLOBAL_REFLOW_COUNT("nsTableFrame", aReflowState.reason);
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
aStatus = NS_FRAME_COMPLETE;
GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
mHaveReflowed = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsPageBreakFrame::GetFrameType(nsIAtom** aType) const
{
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
*aType = nsLayoutAtoms::pageBreakFrame;
NS_ADDREF(*aType);
return NS_OK;
}

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

@ -39,6 +39,7 @@
#include "nsContainerFrame.h"
#include "nsIPrintSettings.h"
#include "nsLeafFrame.h"
class nsSharedPageData;
@ -152,5 +153,28 @@ private:
const nsRect& aDirtyRect);
};
class nsPageBreakFrame : public nsLeafFrame {
nsPageBreakFrame();
~nsPageBreakFrame();
NS_IMETHOD Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus);
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
protected:
virtual void GetDesiredSize(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState,
nsHTMLReflowMetrics& aDesiredSize);
PRBool mHaveReflowed;
friend nsresult NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
};
#endif /* nsPageFrame_h___ */

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

@ -196,6 +196,8 @@ table[rules] {
background: inherit;
border: inherit;
-moz-opacity: inherit;
page-break-before: inherit;
page-break-after: inherit;
}
/* make sure backgrounds are inherited in tables -- see bug 4510*/
@ -509,6 +511,10 @@ noembed, noscript, param {
display: block;
}
*|*:-moz-pagebreak {
display: -moz-page-break;
}
*|*:-moz-anonymous-positioned-block {
display: block;
position: relative;

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

@ -2281,6 +2281,9 @@ nsCSSFrameConstructor::GetParentFrame(nsIPresShell* aPresShell,
}
// Construct the outer, inner table frames and the children frames for the table.
// XXX Page break frames for pseudo table frames are not constructed to avoid the risk
// associated with revising the pseudo frame mechanism. The long term solution
// of having frames handle page-break-before/after will solve the problem.
nsresult
nsCSSFrameConstructor::ConstructTableFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
@ -2923,10 +2926,27 @@ nsCSSFrameConstructor::TableProcessChild(nsIPresShell* aPresShell,
switch (styleDisplay->mDisplay) {
case NS_STYLE_DISPLAY_TABLE:
nsIFrame* innerTableFrame;
rv = ConstructTableFrame(aPresShell, aPresContext, aState, aChildContent, aParentFrame,
childStyleContext, aTableCreator, PR_FALSE, aChildItems,
childFrame, innerTableFrame, isPseudoParent);
{
PRBool pageBreakAfter = PR_FALSE;
PRBool paginated;
aPresContext->IsPaginated(&paginated);
if (paginated) {
// See if there is a page break before, if so construct one. Also see if there is one after
pageBreakAfter = PageBreakBefore(aPresShell, aPresContext, aState, aChildContent,
aParentFrame, childStyleContext, aChildItems);
}
// construct the table frame
nsIFrame* innerTableFrame;
rv = ConstructTableFrame(aPresShell, aPresContext, aState, aChildContent, aParentFrame,
childStyleContext, aTableCreator, PR_FALSE, aChildItems,
childFrame, innerTableFrame, isPseudoParent);
if (NS_SUCCEEDED(rv) && pageBreakAfter) {
// Construct the page break after
ConstructPageBreakFrame(aPresShell, aPresContext, aState, aChildContent,
aParentFrame, childStyleContext, aChildItems);
}
}
break;
case NS_STYLE_DISPLAY_TABLE_CAPTION:
@ -6975,8 +6995,56 @@ nsCSSFrameConstructor::ConstructSVGFrame(nsIPresShell* aPresShell,
}
#endif // MOZ_SVG
PRBool
nsCSSFrameConstructor::PageBreakBefore(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems)
{
const nsStyleDisplay* display = (const nsStyleDisplay*)
aStyleContext->GetStyleData(eStyleStruct_Display);
// See if page-break-before is set for all elements except row groups, rows, cells
// (these are handled internally by tables) and construct a page break frame if so.
if (display && ((NS_STYLE_DISPLAY_TABLE == display->mDisplay) ||
(!IsTableRelated(display->mDisplay, PR_TRUE)))) {
if (display->mBreakBefore) {
ConstructPageBreakFrame(aPresShell, aPresContext, aState, aContent,
aParentFrame, aStyleContext, aFrameItems);
}
return display->mBreakAfter;
}
return PR_FALSE;
}
nsresult
nsCSSFrameConstructor::ConstructFrame(nsIPresShell* aPresShell,
nsCSSFrameConstructor::ConstructPageBreakFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems)
{
nsCOMPtr<nsIStyleContext> pseudoStyle;
aPresContext->ResolvePseudoStyleContextFor(nsnull, nsLayoutAtoms::pageBreakPseudo,
aStyleContext, PR_FALSE,
getter_AddRefs(pseudoStyle));
nsIFrame* pageBreakFrame;
nsresult rv = NS_NewPageBreakFrame(aPresShell, &pageBreakFrame);
if (NS_SUCCEEDED(rv)) {
InitAndRestoreFrame(aPresContext, aState, aContent, aParentFrame,
pseudoStyle, nsnull, pageBreakFrame);
aFrameItems.AddChild(pageBreakFrame);
}
return rv;
}
nsresult
nsCSSFrameConstructor::ConstructFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
@ -7006,20 +7074,27 @@ nsCSSFrameConstructor::ConstructFrame(nsIPresShell* aPresShell,
rv = ResolveStyleContext(aPresContext, aParentFrame, aContent,
getter_AddRefs(styleContext));
if (NS_SUCCEEDED(rv)) {
if (NS_SUCCEEDED(rv)) {
PRInt32 nameSpaceID;
aContent->GetNameSpaceID(nameSpaceID);
rv = ConstructFrameInternal(aPresShell,
aPresContext,
aState,
aContent,
aParentFrame,
tag,
nameSpaceID,
styleContext,
aFrameItems,
PR_FALSE);
PRBool pageBreakAfter = PR_FALSE;
PRBool paginated;
aPresContext->IsPaginated(&paginated);
if (paginated) {
// See if there is a page break before, if so construct one. Also see if there is one after
pageBreakAfter = PageBreakBefore(aPresShell, aPresContext, aState, aContent,
aParentFrame, styleContext, aFrameItems);
}
// construct the frame
rv = ConstructFrameInternal(aPresShell, aPresContext, aState, aContent, aParentFrame,
tag, nameSpaceID, styleContext, aFrameItems, PR_FALSE);
if (NS_SUCCEEDED(rv) && pageBreakAfter) {
// Construct the page break after
ConstructPageBreakFrame(aPresShell, aPresContext, aState, aContent,
aParentFrame, styleContext, aFrameItems);
}
}
return rv;

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

@ -535,6 +535,25 @@ protected:
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems);
nsresult ConstructPageBreakFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems);
// Construct a page break frame if page-break-before:always is set in aStyleContext
// and add it to aFrameItems. Return true if page-break-after:always is set on aStyleContext.
// Don't do this for row groups, rows or cell, because tables handle those internally.
PRBool PageBreakBefore(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,
nsIContent* aContent,
nsIFrame* aParentFrame,
nsIStyleContext* aStyleContext,
nsFrameItems& aFrameItems);
nsresult ConstructHTMLFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext,
nsFrameConstructorState& aState,

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

@ -421,6 +421,32 @@ nsTableFrame::RePositionViews(nsIPresContext* aPresContext,
nsContainerFrame::PositionChildViews(aPresContext, aFrame);
}
PRBool
nsTableFrame::PageBreakAfter(nsIFrame& aSourceFrame,
nsIFrame* aNextFrame)
{
nsCOMPtr<nsIStyleContext> sourceContext;
aSourceFrame.GetStyleContext(getter_AddRefs(sourceContext)); NS_ENSURE_TRUE(sourceContext, PR_FALSE);
const nsStyleDisplay* display = (const nsStyleDisplay*)
sourceContext->GetStyleData(eStyleStruct_Display); NS_ENSURE_TRUE(display, PR_FALSE);
// don't allow a page break after a repeated header
if (display->mBreakAfter && (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP != display->mDisplay)) {
return PR_TRUE;
}
if (aNextFrame) {
nsCOMPtr<nsIStyleContext> nextContext;
aNextFrame->GetStyleContext(getter_AddRefs(nextContext)); NS_ENSURE_TRUE(nextContext, PR_FALSE);
display = (const nsStyleDisplay*)
nextContext->GetStyleData(eStyleStruct_Display); NS_ENSURE_TRUE(display, PR_FALSE);
// don't allow a page break before a repeated footer
if (display->mBreakBefore && (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP != display->mDisplay)) {
return PR_TRUE;
}
}
return PR_FALSE;
}
nsIPresShell*
nsTableFrame::GetPresShellNoAddref(nsIPresContext* aPresContext)
{
@ -1894,6 +1920,9 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
nsReflowReason nextReason = aReflowState.reason;
// Check for an overflow list, and append any row group frames being pushed
MoveOverflowToChildList(aPresContext);
// Processes an initial (except when there is mPrevInFlow), incremental, or style
// change reflow 1st. resize reflows are processed in the next phase.
switch (aReflowState.reason) {
@ -1904,9 +1933,6 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
// NS_ASSERTION(PR_FALSE, "intial reflow called twice");
}
else {
// Check for an overflow list, and append any row group frames being pushed
MoveOverflowToChildList(aPresContext);
if (!mPrevInFlow) { // only do pass1 on a first in flow
if (IsAutoLayout()) {
// only do pass1 reflow on an auto layout table
@ -3203,7 +3229,7 @@ nsTableFrame::ReflowChildren(nsIPresContext* aPresContext,
nsTableRowGroupFrame *thead, *tfoot;
OrderRowGroups(rowGroups, numRowGroups, &aReflowState.firstBodySection, &thead, &tfoot);
PRBool haveReflowedRowGroup = PR_FALSE;
PRBool pageBreak = PR_FALSE;
for (PRUint32 childX = 0; ((PRInt32)childX) < rowGroups.Count(); childX++) {
nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(childX);
// Get the frame state bits
@ -3217,6 +3243,12 @@ nsTableFrame::ReflowChildren(nsIPresContext* aPresContext,
}
if (doReflowChild) {
if (pageBreak) {
PushChildren(aPresContext, kidFrame, prevKidFrame);
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
nsIFrame* repeatedFooter = nsnull;
@ -3264,12 +3296,19 @@ nsTableFrame::ReflowChildren(nsIPresContext* aPresContext,
haveReflowedRowGroup = PR_TRUE;
aLastChildReflowed = kidFrame;
pageBreak = PR_FALSE;
// see if there is a page break after this row group or before the next one
if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight)) {
nsIFrame* nextKid = (childX + 1 < numRowGroups) ? (nsIFrame*)rowGroups.ElementAt(childX + 1) : nsnull;
pageBreak = PageBreakAfter(*kidFrame, nextKid);
}
// Place the child
PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize);
// Remember where we just were in case we end up pushing children
prevKidFrame = kidFrame;
// Special handling for incomplete children
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
kidFrame->GetNextInFlow(&kidNextInFlow);

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

@ -229,6 +229,9 @@ public:
static void RePositionViews(nsIPresContext* aPresContext,
nsIFrame* aFrame);
static PRBool PageBreakAfter(nsIFrame& aSourceFrame,
nsIFrame* aNextFrame);
nsPoint GetFirstSectionOrigin(const nsHTMLReflowState& aReflowState) const;
/*
* Notification that aAttribute has changed for content inside a table (cell, row, etc)

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

@ -359,8 +359,12 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
nsReflowStatus& aStatus,
nsTableRowFrame* aStartFrame,
PRBool aDirtyOnly,
nsTableRowFrame** aFirstRowReflowed)
nsTableRowFrame** aFirstRowReflowed,
PRBool* aPageBreakBeforeEnd)
{
if (aPageBreakBeforeEnd)
*aPageBreakBeforeEnd = PR_FALSE;
nsTableFrame* tableFrame = nsnull;
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(rv);
@ -452,6 +456,14 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
*aFirstRowReflowed = (nsTableRowFrame*)kidFrame;
}
}
if (isPaginated && aPageBreakBeforeEnd && !*aPageBreakBeforeEnd &&
(nsLayoutAtoms::tableRowFrame == kidType.get())) {
nsTableRowFrame* nextRow = ((nsTableRowFrame*)kidFrame)->GetNextRow();
if (nextRow) {
*aPageBreakBeforeEnd = nsTableFrame::PageBreakAfter(*kidFrame, nextRow);
}
}
} else {
// were done reflowing, so see if we need to reposition the rows that follow
if (lastReflowedRow) {
@ -1015,7 +1027,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
// row or there is at least 5% of the current page available
if (!prevRowFrame || (availHeight - aDesiredSize.height > pageHeight / 20)) {
// Reflow the row in the available space and have it split
nsSize availSize(availWidth, availHeight - bounds.y);
nsSize availSize(availWidth, PR_MAX(availHeight - bounds.y, 0));
nsHTMLReflowState rowReflowState(aPresContext, aReflowState, rowFrame, availSize,
eReflowReason_Resize);
InitChildReflowState(*aPresContext, borderCollapse, p2t, rowReflowState);
@ -1085,6 +1097,13 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
aDesiredSize.height = bounds.YMost();
lastDesiredHeight = aDesiredSize.height;
prevRowFrame = rowFrame;
// see if there is a page break after the row
nsTableRowFrame* nextRow = rowFrame->GetNextRow();
if (nextRow && nsTableFrame::PageBreakAfter(*rowFrame, nextRow)) {
PushChildren(aPresContext, nextRow, rowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
break;
}
}
}
return NS_OK;
@ -1143,8 +1162,9 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
}
// Reflow the existing frames.
PRBool splitDueToPageBreak = PR_FALSE;
rv = ReflowChildren(aPresContext, aDesiredSize, state, aStatus,
nsnull, PR_FALSE);
nsnull, PR_FALSE, nsnull, &splitDueToPageBreak);
// Return our desired rect
aDesiredSize.width = aReflowState.availableWidth;
@ -1170,7 +1190,8 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
}
// See if all the frames fit
if ((NS_FRAME_NOT_COMPLETE == aStatus) || (aDesiredSize.height > aReflowState.availableHeight)) {
if ((NS_FRAME_NOT_COMPLETE == aStatus) || splitDueToPageBreak ||
(aDesiredSize.height > aReflowState.availableHeight)) {
// Nope, find a place to split the row group
PRBool specialReflow = (PRBool)aReflowState.mFlags.mSpecialHeightReflow;
((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialHeightReflow = PR_FALSE;

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

@ -325,7 +325,8 @@ protected:
nsReflowStatus& aStatus,
nsTableRowFrame* aStartFrame,
PRBool aDirtyOnly,
nsTableRowFrame** aFirstRowReflowed = nsnull);
nsTableRowFrame** aFirstRowReflowed = nsnull,
PRBool* aPageBreakBeforeEnd = nsnull);
nsresult SplitRowGroup(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,

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

@ -196,6 +196,8 @@ table[rules] {
background: inherit;
border: inherit;
-moz-opacity: inherit;
page-break-before: inherit;
page-break-after: inherit;
}
/* make sure backgrounds are inherited in tables -- see bug 4510*/
@ -509,6 +511,10 @@ noembed, noscript, param {
display: block;
}
*|*:-moz-pagebreak {
display: -moz-page-break;
}
*|*:-moz-anonymous-positioned-block {
display: block;
position: relative;

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

@ -379,6 +379,10 @@ nsCSSDisplay::nsCSSDisplay(const nsCSSDisplay& aCopy)
mPosition(aCopy.mPosition),
mFloat(aCopy.mFloat),
mClear(aCopy.mClear),
// temp fix for bug 24000
mBreakBefore(aCopy.mBreakBefore),
mBreakAfter(aCopy.mBreakAfter),
// end temp
mClip(nsnull),
mOverflow(aCopy.mOverflow),
mVisibility(aCopy.mVisibility),
@ -1794,18 +1798,26 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_ENSURE(Breaks) {
switch (aProperty) {
case eCSSProperty_orphans: theBreaks->mOrphans = aValue; break;
case eCSSProperty_widows: theBreaks->mWidows = aValue; break;
case eCSSProperty_page: theBreaks->mPage = aValue; break;
case eCSSProperty_page_break_after: theBreaks->mPageBreakAfter = aValue; break;
case eCSSProperty_page_break_before: theBreaks->mPageBreakBefore = aValue; break;
case eCSSProperty_page_break_inside: theBreaks->mPageBreakInside = aValue; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_ENSURE(Display) {
switch (aProperty) {
case eCSSProperty_page_break_after: theDisplay->mBreakAfter = aValue; break;
case eCSSProperty_page_break_before: theDisplay->mBreakBefore = aValue; break;
case eCSSProperty_page_break_inside: break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
@ -2739,10 +2751,7 @@ nsCSSDeclaration::SetValueImportant(nsCSSProperty aProperty)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_VARONSTACK_GET(Breaks);
if (nsnull != theBreaks) {
CSS_ENSURE_IMPORTANT(Breaks) {
@ -2750,9 +2759,22 @@ nsCSSDeclaration::SetValueImportant(nsCSSProperty aProperty)
CSS_CASE_IMPORTANT(eCSSProperty_orphans, Breaks, mOrphans);
CSS_CASE_IMPORTANT(eCSSProperty_widows, Breaks, mWidows);
CSS_CASE_IMPORTANT(eCSSProperty_page, Breaks, mPage);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_after, Breaks, mPageBreakAfter);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_before, Breaks, mPageBreakBefore);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_inside, Breaks, mPageBreakInside);
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_VARONSTACK_GET(Display);
if (theDisplay) {
CSS_ENSURE_IMPORTANT(Display) {
switch (aProperty) {
CSS_CASE_IMPORTANT(eCSSProperty_page_break_after, Display, mBreakAfter);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_before, Display, mBreakBefore);
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
@ -3593,24 +3615,30 @@ nsCSSDeclaration::RemoveProperty(nsCSSProperty aProperty)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_CHECK(Breaks) {
switch (aProperty) {
case eCSSProperty_orphans: theBreaks->mOrphans.Reset(); break;
case eCSSProperty_widows: theBreaks->mWidows.Reset(); break;
case eCSSProperty_page: theBreaks->mPage.Reset(); break;
case eCSSProperty_page_break_after: theBreaks->mPageBreakAfter.Reset(); break;
case eCSSProperty_page_break_before: theBreaks->mPageBreakBefore.Reset(); break;
case eCSSProperty_page_break_inside: theBreaks->mPageBreakInside.Reset(); break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_CHECK(Display) {
switch (aProperty) {
case eCSSProperty_page_break_after: theDisplay->mBreakAfter.Reset(); break;
case eCSSProperty_page_break_before: theDisplay->mBreakBefore.Reset(); break;
case eCSSProperty_page_break_inside: break;
}
}
break;
}
// nsCSSPage
case eCSSProperty_marks:
case eCSSProperty_size_width:
@ -4432,19 +4460,31 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_VARONSTACK_GET(Breaks);
if (nsnull != theBreaks) {
switch (aProperty) {
case eCSSProperty_orphans: aValue = theBreaks->mOrphans; break;
case eCSSProperty_widows: aValue = theBreaks->mWidows; break;
case eCSSProperty_page: aValue = theBreaks->mPage; break;
case eCSSProperty_page_break_after: aValue = theBreaks->mPageBreakAfter; break;
case eCSSProperty_page_break_before: aValue = theBreaks->mPageBreakBefore; break;
case eCSSProperty_page_break_inside: aValue = theBreaks->mPageBreakInside; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
else {
aValue.Reset();
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_VARONSTACK_GET(Display);
if (theDisplay) {
switch (aProperty) {
case eCSSProperty_page_break_inside: aValue.Reset(); break;
case eCSSProperty_page_break_after: aValue = theDisplay->mBreakAfter; break;
case eCSSProperty_page_break_before: aValue = theDisplay->mBreakBefore; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}

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

@ -240,6 +240,10 @@ struct nsCSSDisplay : public nsCSSStruct {
// in nsCSSDeclaration objects but because it's needed on the
// stack when the struct is used in WalkRuleTree.
nsCSSValue mLang;
// temp fix for bug 24000
nsCSSValue mBreakBefore;
nsCSSValue mBreakAfter;
// end temp fix
};
struct nsCSSMargin : public nsCSSStruct {

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

@ -99,6 +99,7 @@ CSS_KEY(-moz-inline-grid, _moz_inline_grid)
CSS_KEY(-moz-grid-group, _moz_grid_group)
CSS_KEY(-moz-grid-line, _moz_grid_line)
CSS_KEY(-moz-groupbox, _moz_groupbox)
CSS_KEY(-moz-page-break, _moz_page_break)
CSS_KEY(-moz-popup, _moz_popup)
CSS_KEY(-moz-stack, _moz_stack)
CSS_KEY(-moz-inline-stack, _moz_inline_stack)

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

@ -409,6 +409,7 @@ const PRInt32 nsCSSProps::kDisplayKTable[] = {
eCSSKeyword__moz_bulletinboard, NS_STYLE_DISPLAY_BULLETINBOARD,
eCSSKeyword__moz_popup, NS_STYLE_DISPLAY_POPUP,
eCSSKeyword__moz_groupbox, NS_STYLE_DISPLAY_GROUPBOX,
eCSSKeyword__moz_page_break, NS_STYLE_DISPLAY_PAGE_BREAK,
-1,-1
};

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

@ -379,6 +379,10 @@ nsCSSDisplay::nsCSSDisplay(const nsCSSDisplay& aCopy)
mPosition(aCopy.mPosition),
mFloat(aCopy.mFloat),
mClear(aCopy.mClear),
// temp fix for bug 24000
mBreakBefore(aCopy.mBreakBefore),
mBreakAfter(aCopy.mBreakAfter),
// end temp
mClip(nsnull),
mOverflow(aCopy.mOverflow),
mVisibility(aCopy.mVisibility),
@ -1794,18 +1798,26 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_ENSURE(Breaks) {
switch (aProperty) {
case eCSSProperty_orphans: theBreaks->mOrphans = aValue; break;
case eCSSProperty_widows: theBreaks->mWidows = aValue; break;
case eCSSProperty_page: theBreaks->mPage = aValue; break;
case eCSSProperty_page_break_after: theBreaks->mPageBreakAfter = aValue; break;
case eCSSProperty_page_break_before: theBreaks->mPageBreakBefore = aValue; break;
case eCSSProperty_page_break_inside: theBreaks->mPageBreakInside = aValue; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_ENSURE(Display) {
switch (aProperty) {
case eCSSProperty_page_break_after: theDisplay->mBreakAfter = aValue; break;
case eCSSProperty_page_break_before: theDisplay->mBreakBefore = aValue; break;
case eCSSProperty_page_break_inside: break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
@ -2739,10 +2751,7 @@ nsCSSDeclaration::SetValueImportant(nsCSSProperty aProperty)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_VARONSTACK_GET(Breaks);
if (nsnull != theBreaks) {
CSS_ENSURE_IMPORTANT(Breaks) {
@ -2750,9 +2759,22 @@ nsCSSDeclaration::SetValueImportant(nsCSSProperty aProperty)
CSS_CASE_IMPORTANT(eCSSProperty_orphans, Breaks, mOrphans);
CSS_CASE_IMPORTANT(eCSSProperty_widows, Breaks, mWidows);
CSS_CASE_IMPORTANT(eCSSProperty_page, Breaks, mPage);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_after, Breaks, mPageBreakAfter);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_before, Breaks, mPageBreakBefore);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_inside, Breaks, mPageBreakInside);
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_VARONSTACK_GET(Display);
if (theDisplay) {
CSS_ENSURE_IMPORTANT(Display) {
switch (aProperty) {
CSS_CASE_IMPORTANT(eCSSProperty_page_break_after, Display, mBreakAfter);
CSS_CASE_IMPORTANT(eCSSProperty_page_break_before, Display, mBreakBefore);
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
@ -3593,24 +3615,30 @@ nsCSSDeclaration::RemoveProperty(nsCSSProperty aProperty)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_CHECK(Breaks) {
switch (aProperty) {
case eCSSProperty_orphans: theBreaks->mOrphans.Reset(); break;
case eCSSProperty_widows: theBreaks->mWidows.Reset(); break;
case eCSSProperty_page: theBreaks->mPage.Reset(); break;
case eCSSProperty_page_break_after: theBreaks->mPageBreakAfter.Reset(); break;
case eCSSProperty_page_break_before: theBreaks->mPageBreakBefore.Reset(); break;
case eCSSProperty_page_break_inside: theBreaks->mPageBreakInside.Reset(); break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_CHECK(Display) {
switch (aProperty) {
case eCSSProperty_page_break_after: theDisplay->mBreakAfter.Reset(); break;
case eCSSProperty_page_break_before: theDisplay->mBreakBefore.Reset(); break;
case eCSSProperty_page_break_inside: break;
}
}
break;
}
// nsCSSPage
case eCSSProperty_marks:
case eCSSProperty_size_width:
@ -4432,19 +4460,31 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue)
// nsCSSBreaks
case eCSSProperty_orphans:
case eCSSProperty_widows:
case eCSSProperty_page:
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
case eCSSProperty_page: {
CSS_VARONSTACK_GET(Breaks);
if (nsnull != theBreaks) {
switch (aProperty) {
case eCSSProperty_orphans: aValue = theBreaks->mOrphans; break;
case eCSSProperty_widows: aValue = theBreaks->mWidows; break;
case eCSSProperty_page: aValue = theBreaks->mPage; break;
case eCSSProperty_page_break_after: aValue = theBreaks->mPageBreakAfter; break;
case eCSSProperty_page_break_before: aValue = theBreaks->mPageBreakBefore; break;
case eCSSProperty_page_break_inside: aValue = theBreaks->mPageBreakInside; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}
else {
aValue.Reset();
}
break;
}
case eCSSProperty_page_break_after:
case eCSSProperty_page_break_before:
case eCSSProperty_page_break_inside: {
// temp fix for bug 24000
CSS_VARONSTACK_GET(Display);
if (theDisplay) {
switch (aProperty) {
case eCSSProperty_page_break_inside: aValue.Reset(); break;
case eCSSProperty_page_break_after: aValue = theDisplay->mBreakAfter; break;
case eCSSProperty_page_break_before: aValue = theDisplay->mBreakBefore; break;
CSS_BOGUS_DEFAULT; // make compiler happy
}
}

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

@ -240,6 +240,10 @@ struct nsCSSDisplay : public nsCSSStruct {
// in nsCSSDeclaration objects but because it's needed on the
// stack when the struct is used in WalkRuleTree.
nsCSSValue mLang;
// temp fix for bug 24000
nsCSSValue mBreakBefore;
nsCSSValue mBreakAfter;
// end temp fix
};
struct nsCSSMargin : public nsCSSStruct {

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

@ -2306,6 +2306,13 @@ MapDisplayForDeclaration(nsCSSDeclaration* aDecl, const nsStyleStructID& aID, ns
if (aDisplay.mClear.GetUnit() == eCSSUnit_Null && ourDisplay->mClear.GetUnit() != eCSSUnit_Null)
aDisplay.mClear = ourDisplay->mClear;
// temp fix for bug 24000
if (aDisplay.mBreakBefore.GetUnit() == eCSSUnit_Null && ourDisplay->mBreakBefore.GetUnit() != eCSSUnit_Null)
aDisplay.mBreakBefore = ourDisplay->mBreakBefore;
if (aDisplay.mBreakAfter.GetUnit() == eCSSUnit_Null && ourDisplay->mBreakAfter.GetUnit() != eCSSUnit_Null)
aDisplay.mBreakAfter = ourDisplay->mBreakAfter;
// end temp fix
// float: enum, none, inherit
if (aDisplay.mFloat.GetUnit() == eCSSUnit_Null && ourDisplay->mFloat.GetUnit() != eCSSUnit_Null)
aDisplay.mFloat = ourDisplay->mFloat;

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

@ -783,7 +783,9 @@ static const PropertyCheckData DisplayCheckProperties[] = {
CHECKDATA_PROP(nsCSSDisplay, mPosition, CHECKDATA_VALUE, PR_FALSE),
CHECKDATA_PROP(nsCSSDisplay, mFloat, CHECKDATA_VALUE, PR_FALSE),
CHECKDATA_PROP(nsCSSDisplay, mClear, CHECKDATA_VALUE, PR_FALSE),
CHECKDATA_PROP(nsCSSDisplay, mOverflow, CHECKDATA_VALUE, PR_FALSE)
CHECKDATA_PROP(nsCSSDisplay, mOverflow, CHECKDATA_VALUE, PR_FALSE),
CHECKDATA_PROP(nsCSSDisplay, mBreakBefore, CHECKDATA_VALUE, PR_FALSE), // temp fix for bug 2400
CHECKDATA_PROP(nsCSSDisplay, mBreakAfter, CHECKDATA_VALUE, PR_FALSE) // temp fix for bug 2400
};
static const PropertyCheckData VisibilityCheckProperties[] = {
@ -2824,6 +2826,15 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct, const nsCSSStruct& a
display->mBreakType = parentDisplay->mBreakType;
}
// temp fix for bug 24000
if (eCSSUnit_Enumerated == displayData.mBreakBefore.GetUnit()) {
display->mBreakBefore = (NS_STYLE_PAGE_BREAK_ALWAYS == displayData.mBreakBefore.GetIntValue());
}
if (eCSSUnit_Enumerated == displayData.mBreakAfter.GetUnit()) {
display->mBreakAfter = (NS_STYLE_PAGE_BREAK_ALWAYS == displayData.mBreakAfter.GetIntValue());
}
// end temp fix
// float: enum, none, inherit
if (eCSSUnit_Enumerated == displayData.mFloat.GetUnit()) {
display->mFloats = displayData.mFloat.GetIntValue();

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

@ -421,6 +421,32 @@ nsTableFrame::RePositionViews(nsIPresContext* aPresContext,
nsContainerFrame::PositionChildViews(aPresContext, aFrame);
}
PRBool
nsTableFrame::PageBreakAfter(nsIFrame& aSourceFrame,
nsIFrame* aNextFrame)
{
nsCOMPtr<nsIStyleContext> sourceContext;
aSourceFrame.GetStyleContext(getter_AddRefs(sourceContext)); NS_ENSURE_TRUE(sourceContext, PR_FALSE);
const nsStyleDisplay* display = (const nsStyleDisplay*)
sourceContext->GetStyleData(eStyleStruct_Display); NS_ENSURE_TRUE(display, PR_FALSE);
// don't allow a page break after a repeated header
if (display->mBreakAfter && (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP != display->mDisplay)) {
return PR_TRUE;
}
if (aNextFrame) {
nsCOMPtr<nsIStyleContext> nextContext;
aNextFrame->GetStyleContext(getter_AddRefs(nextContext)); NS_ENSURE_TRUE(nextContext, PR_FALSE);
display = (const nsStyleDisplay*)
nextContext->GetStyleData(eStyleStruct_Display); NS_ENSURE_TRUE(display, PR_FALSE);
// don't allow a page break before a repeated footer
if (display->mBreakBefore && (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP != display->mDisplay)) {
return PR_TRUE;
}
}
return PR_FALSE;
}
nsIPresShell*
nsTableFrame::GetPresShellNoAddref(nsIPresContext* aPresContext)
{
@ -1894,6 +1920,9 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
nsReflowReason nextReason = aReflowState.reason;
// Check for an overflow list, and append any row group frames being pushed
MoveOverflowToChildList(aPresContext);
// Processes an initial (except when there is mPrevInFlow), incremental, or style
// change reflow 1st. resize reflows are processed in the next phase.
switch (aReflowState.reason) {
@ -1904,9 +1933,6 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
// NS_ASSERTION(PR_FALSE, "intial reflow called twice");
}
else {
// Check for an overflow list, and append any row group frames being pushed
MoveOverflowToChildList(aPresContext);
if (!mPrevInFlow) { // only do pass1 on a first in flow
if (IsAutoLayout()) {
// only do pass1 reflow on an auto layout table
@ -3203,7 +3229,7 @@ nsTableFrame::ReflowChildren(nsIPresContext* aPresContext,
nsTableRowGroupFrame *thead, *tfoot;
OrderRowGroups(rowGroups, numRowGroups, &aReflowState.firstBodySection, &thead, &tfoot);
PRBool haveReflowedRowGroup = PR_FALSE;
PRBool pageBreak = PR_FALSE;
for (PRUint32 childX = 0; ((PRInt32)childX) < rowGroups.Count(); childX++) {
nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(childX);
// Get the frame state bits
@ -3217,6 +3243,12 @@ nsTableFrame::ReflowChildren(nsIPresContext* aPresContext,
}
if (doReflowChild) {
if (pageBreak) {
PushChildren(aPresContext, kidFrame, prevKidFrame);
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
nsIFrame* repeatedFooter = nsnull;
@ -3264,12 +3296,19 @@ nsTableFrame::ReflowChildren(nsIPresContext* aPresContext,
haveReflowedRowGroup = PR_TRUE;
aLastChildReflowed = kidFrame;
pageBreak = PR_FALSE;
// see if there is a page break after this row group or before the next one
if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight)) {
nsIFrame* nextKid = (childX + 1 < numRowGroups) ? (nsIFrame*)rowGroups.ElementAt(childX + 1) : nsnull;
pageBreak = PageBreakAfter(*kidFrame, nextKid);
}
// Place the child
PlaceChild(aPresContext, aReflowState, kidFrame, desiredSize);
// Remember where we just were in case we end up pushing children
prevKidFrame = kidFrame;
// Special handling for incomplete children
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
kidFrame->GetNextInFlow(&kidNextInFlow);

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

@ -229,6 +229,9 @@ public:
static void RePositionViews(nsIPresContext* aPresContext,
nsIFrame* aFrame);
static PRBool PageBreakAfter(nsIFrame& aSourceFrame,
nsIFrame* aNextFrame);
nsPoint GetFirstSectionOrigin(const nsHTMLReflowState& aReflowState) const;
/*
* Notification that aAttribute has changed for content inside a table (cell, row, etc)

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

@ -359,8 +359,12 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
nsReflowStatus& aStatus,
nsTableRowFrame* aStartFrame,
PRBool aDirtyOnly,
nsTableRowFrame** aFirstRowReflowed)
nsTableRowFrame** aFirstRowReflowed,
PRBool* aPageBreakBeforeEnd)
{
if (aPageBreakBeforeEnd)
*aPageBreakBeforeEnd = PR_FALSE;
nsTableFrame* tableFrame = nsnull;
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(rv);
@ -452,6 +456,14 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
*aFirstRowReflowed = (nsTableRowFrame*)kidFrame;
}
}
if (isPaginated && aPageBreakBeforeEnd && !*aPageBreakBeforeEnd &&
(nsLayoutAtoms::tableRowFrame == kidType.get())) {
nsTableRowFrame* nextRow = ((nsTableRowFrame*)kidFrame)->GetNextRow();
if (nextRow) {
*aPageBreakBeforeEnd = nsTableFrame::PageBreakAfter(*kidFrame, nextRow);
}
}
} else {
// were done reflowing, so see if we need to reposition the rows that follow
if (lastReflowedRow) {
@ -1015,7 +1027,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
// row or there is at least 5% of the current page available
if (!prevRowFrame || (availHeight - aDesiredSize.height > pageHeight / 20)) {
// Reflow the row in the available space and have it split
nsSize availSize(availWidth, availHeight - bounds.y);
nsSize availSize(availWidth, PR_MAX(availHeight - bounds.y, 0));
nsHTMLReflowState rowReflowState(aPresContext, aReflowState, rowFrame, availSize,
eReflowReason_Resize);
InitChildReflowState(*aPresContext, borderCollapse, p2t, rowReflowState);
@ -1085,6 +1097,13 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
aDesiredSize.height = bounds.YMost();
lastDesiredHeight = aDesiredSize.height;
prevRowFrame = rowFrame;
// see if there is a page break after the row
nsTableRowFrame* nextRow = rowFrame->GetNextRow();
if (nextRow && nsTableFrame::PageBreakAfter(*rowFrame, nextRow)) {
PushChildren(aPresContext, nextRow, rowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
break;
}
}
}
return NS_OK;
@ -1143,8 +1162,9 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
}
// Reflow the existing frames.
PRBool splitDueToPageBreak = PR_FALSE;
rv = ReflowChildren(aPresContext, aDesiredSize, state, aStatus,
nsnull, PR_FALSE);
nsnull, PR_FALSE, nsnull, &splitDueToPageBreak);
// Return our desired rect
aDesiredSize.width = aReflowState.availableWidth;
@ -1170,7 +1190,8 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
}
// See if all the frames fit
if ((NS_FRAME_NOT_COMPLETE == aStatus) || (aDesiredSize.height > aReflowState.availableHeight)) {
if ((NS_FRAME_NOT_COMPLETE == aStatus) || splitDueToPageBreak ||
(aDesiredSize.height > aReflowState.availableHeight)) {
// Nope, find a place to split the row group
PRBool specialReflow = (PRBool)aReflowState.mFlags.mSpecialHeightReflow;
((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialHeightReflow = PR_FALSE;

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

@ -325,7 +325,8 @@ protected:
nsReflowStatus& aStatus,
nsTableRowFrame* aStartFrame,
PRBool aDirtyOnly,
nsTableRowFrame** aFirstRowReflowed = nsnull);
nsTableRowFrame** aFirstRowReflowed = nsnull,
PRBool* aPageBreakBeforeEnd = nsnull);
nsresult SplitRowGroup(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,