Relanding fix for bug Bug 219693, r+sr=dbaron

This commit is contained in:
bzbarsky%mit.edu 2003-10-06 13:13:37 +00:00
Родитель 7969933f91
Коммит d6608ce74f
2 изменённых файлов: 80 добавлений и 74 удалений

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

@ -36,6 +36,7 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsCSSAnonBoxes.h"
#include "nsFrame.h" #include "nsFrame.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsHTMLAtoms.h" #include "nsHTMLAtoms.h"
@ -1359,20 +1360,22 @@ GetVerticalMarginBorderPadding(const nsHTMLReflowState* aReflowState)
/* Get the height based on the viewport of the containing block specified /* Get the height based on the viewport of the containing block specified
* in aReflowState when the containing block has mComputedHeight == NS_AUTOHEIGHT * in aReflowState when the containing block has mComputedHeight == NS_AUTOHEIGHT
* This will walk up the chain of containing blocks looking for a computed height * This will walk up the chain of containing blocks looking for a computed height
* until it finds the canvas frame, or it encounters a frame that is not a block * until it finds the canvas frame, or it encounters a frame that is not a block,
* or and area frame. This handles compatibility with IE (see bug 85016) * area, or scroll frame. This handles compatibility with IE (see bug 85016 and bug 219693)
* *
* When the argument aRestrictToFirstLevel is TRUE, we stop looking after the first parent * When the argument aRestrictToFirstLevel is TRUE, we stop looking after the second parent
* block or area frame. When FALSE, we look all the way up the frame tree, through nested * block, area, or scroll frame. When FALSE, we look all the way up the frame tree, through nested
* blocks and area frames, and always find a real height. This is needed for percentage-height * block, area, and scroll frames, and always find a real height. This is needed for percentage-height
* images in unconstrained blocks, like DIVs (see bugzilla bug 85016) * images in unconstrained blocks, like DIVs (see bugzilla bug 85016).
*
* When we encounter scrolledContent area frames, we skip over them, since they are guaranteed to not be useful for computing the containing block.
*/ */
nscoord nscoord
CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
PRBool aRestrictToFirstLevel) PRBool aRestrictToFirstLevel)
{ {
nsHTMLReflowState* firstBlockRS = nsnull; // a candidate for body frame nsHTMLReflowState* firstAncestorRS = nsnull; // a candidate for html frame
nsHTMLReflowState* firstAreaRS = nsnull; // a candidate for html frame nsHTMLReflowState* secondAncestorRS = nsnull; // a candidate for body frame
// initialize the default to NS_AUTOHEIGHT as this is the containings block // initialize the default to NS_AUTOHEIGHT as this is the containings block
// computed height when this function is called. It is possible that we // computed height when this function is called. It is possible that we
@ -1385,25 +1388,25 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
rs->frame->GetFrameType(getter_AddRefs(frameType)); rs->frame->GetFrameType(getter_AddRefs(frameType));
// if the ancestor is auto height then skip it and continue up if it // if the ancestor is auto height then skip it and continue up if it
// is the first block/area frame and possibly the body/html // is the first block/area frame and possibly the body/html
if (nsLayoutAtoms::blockFrame == frameType.get()) { if (nsLayoutAtoms::blockFrame == frameType ||
if (aRestrictToFirstLevel && firstBlockRS) { nsLayoutAtoms::areaFrame == frameType ||
nsLayoutAtoms::scrollFrame == frameType) {
if (nsLayoutAtoms::areaFrame == frameType) {
nsCOMPtr<nsIAtom> pseudo = rs->frame->GetStyleContext()->GetPseudoType();
if (pseudo == nsCSSAnonBoxes::scrolledContent) {
continue;
}
}
if (aRestrictToFirstLevel && firstAncestorRS && secondAncestorRS) {
break; break;
} }
firstBlockRS = (nsHTMLReflowState*)rs; secondAncestorRS = firstAncestorRS;
firstAncestorRS = (nsHTMLReflowState*)rs;
if (NS_AUTOHEIGHT == rs->mComputedHeight) { if (NS_AUTOHEIGHT == rs->mComputedHeight) {
continue; continue;
} }
} }
else if (nsLayoutAtoms::areaFrame == frameType.get()) { else if (nsLayoutAtoms::canvasFrame == frameType) {
if (aRestrictToFirstLevel && firstAreaRS) {
break;
}
firstAreaRS = (nsHTMLReflowState*)rs;
if (NS_AUTOHEIGHT == rs->mComputedHeight) {
continue;
}
}
else if (nsLayoutAtoms::canvasFrame == frameType.get()) {
// Use scroll frames' computed height if we have one, this will // Use scroll frames' computed height if we have one, this will
// allow us to get viewport height for native scrollbars. // allow us to get viewport height for native scrollbars.
nsHTMLReflowState* scrollState = (nsHTMLReflowState *)rs->parentReflowState; nsHTMLReflowState* scrollState = (nsHTMLReflowState *)rs->parentReflowState;
@ -1413,7 +1416,7 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
rs = scrollState; rs = scrollState;
} }
} }
else if (nsLayoutAtoms::pageContentFrame == frameType.get()) { else if (nsLayoutAtoms::pageContentFrame == frameType) {
nsIFrame* prevInFlow; nsIFrame* prevInFlow;
rs->frame->GetPrevInFlow(&prevInFlow); rs->frame->GetPrevInFlow(&prevInFlow);
// only use the page content frame for a height basis if it is the first in flow // only use the page content frame for a height basis if it is the first in flow
@ -1426,35 +1429,35 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
// if the ancestor is the page content frame then the percent base is // if the ancestor is the page content frame then the percent base is
// the avail height, otherwise it is the computed height // the avail height, otherwise it is the computed height
result = (nsLayoutAtoms::pageContentFrame == frameType.get()) result = (nsLayoutAtoms::pageContentFrame == frameType)
? rs->availableHeight : rs->mComputedHeight; ? rs->availableHeight : rs->mComputedHeight;
// if unconstrained - don't sutract borders - would result in huge height // if unconstrained - don't sutract borders - would result in huge height
if (NS_AUTOHEIGHT == result) return result; if (NS_AUTOHEIGHT == result) return result;
// if we got to the canvas or page content frame, then subtract out // if we got to the canvas or page content frame, then subtract out
// margin/border/padding for the BODY and HTML elements // margin/border/padding for the BODY and HTML elements
if ((nsLayoutAtoms::canvasFrame == frameType.get()) || if ((nsLayoutAtoms::canvasFrame == frameType) ||
(nsLayoutAtoms::pageContentFrame == frameType.get())) { (nsLayoutAtoms::pageContentFrame == frameType)) {
result -= GetVerticalMarginBorderPadding(firstBlockRS); result -= GetVerticalMarginBorderPadding(firstAncestorRS);
result -= GetVerticalMarginBorderPadding(firstAreaRS); result -= GetVerticalMarginBorderPadding(secondAncestorRS);
#ifdef DEBUG #ifdef DEBUG
// make sure the Area is the HTML and the Block is the BODY // make sure the first ancestor is the HTML and the second is the BODY
if (firstBlockRS) { if (firstAncestorRS) {
nsIContent* frameContent = firstBlockRS->frame->GetContent(); nsIContent* frameContent = firstAncestorRS->frame->GetContent();
if (frameContent) { if (frameContent) {
nsCOMPtr<nsIAtom> contentTag; nsCOMPtr<nsIAtom> contentTag;
frameContent->GetTag(getter_AddRefs(contentTag)); frameContent->GetTag(getter_AddRefs(contentTag));
NS_ASSERTION(contentTag.get() == nsHTMLAtoms::body, "block is not BODY"); NS_ASSERTION(contentTag == nsHTMLAtoms::html, "First ancestor is not HTML");
} }
} }
if (firstAreaRS) { if (secondAncestorRS) {
nsIContent* frameContent = firstAreaRS->frame->GetContent(); nsIContent* frameContent = secondAncestorRS->frame->GetContent();
if (frameContent) { if (frameContent) {
nsCOMPtr<nsIAtom> contentTag; nsCOMPtr<nsIAtom> contentTag;
frameContent->GetTag(getter_AddRefs(contentTag)); frameContent->GetTag(getter_AddRefs(contentTag));
NS_ASSERTION(contentTag.get() == nsHTMLAtoms::html, "Area frame is not HTML element"); NS_ASSERTION(contentTag == nsHTMLAtoms::body, "Second ancestor is not BODY");
} }
} }
#endif #endif
@ -1462,12 +1465,12 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
} }
// if we got to the html frame, then subtract out // if we got to the html frame, then subtract out
// margin/border/padding for the BODY element // margin/border/padding for the BODY element
else if (nsLayoutAtoms::areaFrame == frameType.get()) { else if (nsLayoutAtoms::areaFrame == frameType) {
// make sure it is the body // make sure it is the body
nsCOMPtr<nsIAtom> fType; nsCOMPtr<nsIAtom> fType;
rs->parentReflowState->frame->GetFrameType(getter_AddRefs(fType)); rs->parentReflowState->frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::canvasFrame == fType.get()) { if (nsLayoutAtoms::canvasFrame == fType) {
result -= GetVerticalMarginBorderPadding(firstBlockRS); result -= GetVerticalMarginBorderPadding(secondAncestorRS);
} }
} }
break; break;

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

@ -36,6 +36,7 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsCSSAnonBoxes.h"
#include "nsFrame.h" #include "nsFrame.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsHTMLAtoms.h" #include "nsHTMLAtoms.h"
@ -1359,20 +1360,22 @@ GetVerticalMarginBorderPadding(const nsHTMLReflowState* aReflowState)
/* Get the height based on the viewport of the containing block specified /* Get the height based on the viewport of the containing block specified
* in aReflowState when the containing block has mComputedHeight == NS_AUTOHEIGHT * in aReflowState when the containing block has mComputedHeight == NS_AUTOHEIGHT
* This will walk up the chain of containing blocks looking for a computed height * This will walk up the chain of containing blocks looking for a computed height
* until it finds the canvas frame, or it encounters a frame that is not a block * until it finds the canvas frame, or it encounters a frame that is not a block,
* or and area frame. This handles compatibility with IE (see bug 85016) * area, or scroll frame. This handles compatibility with IE (see bug 85016 and bug 219693)
* *
* When the argument aRestrictToFirstLevel is TRUE, we stop looking after the first parent * When the argument aRestrictToFirstLevel is TRUE, we stop looking after the second parent
* block or area frame. When FALSE, we look all the way up the frame tree, through nested * block, area, or scroll frame. When FALSE, we look all the way up the frame tree, through nested
* blocks and area frames, and always find a real height. This is needed for percentage-height * block, area, and scroll frames, and always find a real height. This is needed for percentage-height
* images in unconstrained blocks, like DIVs (see bugzilla bug 85016) * images in unconstrained blocks, like DIVs (see bugzilla bug 85016).
*
* When we encounter scrolledContent area frames, we skip over them, since they are guaranteed to not be useful for computing the containing block.
*/ */
nscoord nscoord
CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState, CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
PRBool aRestrictToFirstLevel) PRBool aRestrictToFirstLevel)
{ {
nsHTMLReflowState* firstBlockRS = nsnull; // a candidate for body frame nsHTMLReflowState* firstAncestorRS = nsnull; // a candidate for html frame
nsHTMLReflowState* firstAreaRS = nsnull; // a candidate for html frame nsHTMLReflowState* secondAncestorRS = nsnull; // a candidate for body frame
// initialize the default to NS_AUTOHEIGHT as this is the containings block // initialize the default to NS_AUTOHEIGHT as this is the containings block
// computed height when this function is called. It is possible that we // computed height when this function is called. It is possible that we
@ -1385,25 +1388,25 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
rs->frame->GetFrameType(getter_AddRefs(frameType)); rs->frame->GetFrameType(getter_AddRefs(frameType));
// if the ancestor is auto height then skip it and continue up if it // if the ancestor is auto height then skip it and continue up if it
// is the first block/area frame and possibly the body/html // is the first block/area frame and possibly the body/html
if (nsLayoutAtoms::blockFrame == frameType.get()) { if (nsLayoutAtoms::blockFrame == frameType ||
if (aRestrictToFirstLevel && firstBlockRS) { nsLayoutAtoms::areaFrame == frameType ||
nsLayoutAtoms::scrollFrame == frameType) {
if (nsLayoutAtoms::areaFrame == frameType) {
nsCOMPtr<nsIAtom> pseudo = rs->frame->GetStyleContext()->GetPseudoType();
if (pseudo == nsCSSAnonBoxes::scrolledContent) {
continue;
}
}
if (aRestrictToFirstLevel && firstAncestorRS && secondAncestorRS) {
break; break;
} }
firstBlockRS = (nsHTMLReflowState*)rs; secondAncestorRS = firstAncestorRS;
firstAncestorRS = (nsHTMLReflowState*)rs;
if (NS_AUTOHEIGHT == rs->mComputedHeight) { if (NS_AUTOHEIGHT == rs->mComputedHeight) {
continue; continue;
} }
} }
else if (nsLayoutAtoms::areaFrame == frameType.get()) { else if (nsLayoutAtoms::canvasFrame == frameType) {
if (aRestrictToFirstLevel && firstAreaRS) {
break;
}
firstAreaRS = (nsHTMLReflowState*)rs;
if (NS_AUTOHEIGHT == rs->mComputedHeight) {
continue;
}
}
else if (nsLayoutAtoms::canvasFrame == frameType.get()) {
// Use scroll frames' computed height if we have one, this will // Use scroll frames' computed height if we have one, this will
// allow us to get viewport height for native scrollbars. // allow us to get viewport height for native scrollbars.
nsHTMLReflowState* scrollState = (nsHTMLReflowState *)rs->parentReflowState; nsHTMLReflowState* scrollState = (nsHTMLReflowState *)rs->parentReflowState;
@ -1413,7 +1416,7 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
rs = scrollState; rs = scrollState;
} }
} }
else if (nsLayoutAtoms::pageContentFrame == frameType.get()) { else if (nsLayoutAtoms::pageContentFrame == frameType) {
nsIFrame* prevInFlow; nsIFrame* prevInFlow;
rs->frame->GetPrevInFlow(&prevInFlow); rs->frame->GetPrevInFlow(&prevInFlow);
// only use the page content frame for a height basis if it is the first in flow // only use the page content frame for a height basis if it is the first in flow
@ -1426,35 +1429,35 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
// if the ancestor is the page content frame then the percent base is // if the ancestor is the page content frame then the percent base is
// the avail height, otherwise it is the computed height // the avail height, otherwise it is the computed height
result = (nsLayoutAtoms::pageContentFrame == frameType.get()) result = (nsLayoutAtoms::pageContentFrame == frameType)
? rs->availableHeight : rs->mComputedHeight; ? rs->availableHeight : rs->mComputedHeight;
// if unconstrained - don't sutract borders - would result in huge height // if unconstrained - don't sutract borders - would result in huge height
if (NS_AUTOHEIGHT == result) return result; if (NS_AUTOHEIGHT == result) return result;
// if we got to the canvas or page content frame, then subtract out // if we got to the canvas or page content frame, then subtract out
// margin/border/padding for the BODY and HTML elements // margin/border/padding for the BODY and HTML elements
if ((nsLayoutAtoms::canvasFrame == frameType.get()) || if ((nsLayoutAtoms::canvasFrame == frameType) ||
(nsLayoutAtoms::pageContentFrame == frameType.get())) { (nsLayoutAtoms::pageContentFrame == frameType)) {
result -= GetVerticalMarginBorderPadding(firstBlockRS); result -= GetVerticalMarginBorderPadding(firstAncestorRS);
result -= GetVerticalMarginBorderPadding(firstAreaRS); result -= GetVerticalMarginBorderPadding(secondAncestorRS);
#ifdef DEBUG #ifdef DEBUG
// make sure the Area is the HTML and the Block is the BODY // make sure the first ancestor is the HTML and the second is the BODY
if (firstBlockRS) { if (firstAncestorRS) {
nsIContent* frameContent = firstBlockRS->frame->GetContent(); nsIContent* frameContent = firstAncestorRS->frame->GetContent();
if (frameContent) { if (frameContent) {
nsCOMPtr<nsIAtom> contentTag; nsCOMPtr<nsIAtom> contentTag;
frameContent->GetTag(getter_AddRefs(contentTag)); frameContent->GetTag(getter_AddRefs(contentTag));
NS_ASSERTION(contentTag.get() == nsHTMLAtoms::body, "block is not BODY"); NS_ASSERTION(contentTag == nsHTMLAtoms::html, "First ancestor is not HTML");
} }
} }
if (firstAreaRS) { if (secondAncestorRS) {
nsIContent* frameContent = firstAreaRS->frame->GetContent(); nsIContent* frameContent = secondAncestorRS->frame->GetContent();
if (frameContent) { if (frameContent) {
nsCOMPtr<nsIAtom> contentTag; nsCOMPtr<nsIAtom> contentTag;
frameContent->GetTag(getter_AddRefs(contentTag)); frameContent->GetTag(getter_AddRefs(contentTag));
NS_ASSERTION(contentTag.get() == nsHTMLAtoms::html, "Area frame is not HTML element"); NS_ASSERTION(contentTag == nsHTMLAtoms::body, "Second ancestor is not BODY");
} }
} }
#endif #endif
@ -1462,12 +1465,12 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
} }
// if we got to the html frame, then subtract out // if we got to the html frame, then subtract out
// margin/border/padding for the BODY element // margin/border/padding for the BODY element
else if (nsLayoutAtoms::areaFrame == frameType.get()) { else if (nsLayoutAtoms::areaFrame == frameType) {
// make sure it is the body // make sure it is the body
nsCOMPtr<nsIAtom> fType; nsCOMPtr<nsIAtom> fType;
rs->parentReflowState->frame->GetFrameType(getter_AddRefs(fType)); rs->parentReflowState->frame->GetFrameType(getter_AddRefs(fType));
if (nsLayoutAtoms::canvasFrame == fType.get()) { if (nsLayoutAtoms::canvasFrame == fType) {
result -= GetVerticalMarginBorderPadding(firstBlockRS); result -= GetVerticalMarginBorderPadding(secondAncestorRS);
} }
} }
break; break;