diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index c467bb969c35..e5e0e4660bde 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -5994,24 +5994,6 @@ nsBlockFrame::RecoverFloatsFor(nsIFrame* aFrame, ////////////////////////////////////////////////////////////////////// // Painting, event handling -int -nsBlockFrame::GetSkipSides() const -{ - if (IS_TRUE_OVERFLOW_CONTAINER(this)) { - return (1 << NS_SIDE_TOP) | (1 << NS_SIDE_BOTTOM); - } - - int skip = 0; - if (GetPrevInFlow()) { - skip |= 1 << NS_SIDE_TOP; - } - nsIFrame* nif = GetNextInFlow(); - if (nif && !IS_TRUE_OVERFLOW_CONTAINER(nif)) { - skip |= 1 << NS_SIDE_BOTTOM; - } - return skip; -} - #ifdef DEBUG static void ComputeVisualOverflowArea(nsLineList& aLines, nscoord aWidth, nscoord aHeight, diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 96cef618d518..a83227074199 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -412,8 +412,6 @@ protected: void SlideLine(nsBlockReflowState& aState, nsLineBox* aLine, nscoord aDY); - virtual int GetSkipSides() const MOZ_OVERRIDE; - void ComputeFinalSize(const nsHTMLReflowState& aReflowState, nsBlockReflowState& aState, nsHTMLReflowMetrics& aMetrics, diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 835f3d8f128a..f7a18068e1dd 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -1100,7 +1100,7 @@ nsFlexContainerFrame::GetType() const /* virtual */ int -nsFlexContainerFrame::GetSkipSides() const +nsFlexContainerFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const { // (same as nsBlockFrame's GetSkipSides impl) if (IS_TRUE_OVERFLOW_CONTAINER(this)) { diff --git a/layout/generic/nsFlexContainerFrame.h b/layout/generic/nsFlexContainerFrame.h index b83273fda098..618187c878d0 100644 --- a/layout/generic/nsFlexContainerFrame.h +++ b/layout/generic/nsFlexContainerFrame.h @@ -50,7 +50,7 @@ public: GetPrefWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; virtual nsIAtom* GetType() const MOZ_OVERRIDE; - virtual int GetSkipSides() const MOZ_OVERRIDE; + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; #ifdef DEBUG NS_IMETHOD GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; #endif // DEBUG diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 83d2f8bc6294..b47a2750e142 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -958,9 +958,10 @@ nsIFrame::GetUsedPadding() const } void -nsIFrame::ApplySkipSides(nsMargin& aMargin) const +nsIFrame::ApplySkipSides(nsMargin& aMargin, + const nsHTMLReflowState* aReflowState) const { - int skipSides = GetSkipSides(); + int skipSides = GetSkipSides(aReflowState); if (skipSides & (1 << NS_SIDE_TOP)) aMargin.top = 0; if (skipSides & (1 << NS_SIDE_RIGHT)) diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index c217b46ab199..86cae8e68ca9 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -985,8 +985,21 @@ public: /** * Apply the result of GetSkipSides() on this frame to an nsMargin by * setting to zero any sides that are skipped. + * + * @param aMargin The margin to apply the result of GetSkipSides() to. + * @param aReflowState An optional reflow state parameter, which is used if + * ApplySkipSides() is being called in the middle of reflow. + * + * @note (See also bug 743402, comment 11) GetSkipSides() and it's sister + * method, ApplySkipSides() checks to see if this frame has a previous + * or next continuation to determine if a side should be skipped. + * Unfortunately, this only works after reflow has been completed. In + * lieu of this, during reflow, an nsHTMLReflowState parameter can be + * passed in, indicating that it should be used to determine if sides + * should be skipped during reflow. */ - void ApplySkipSides(nsMargin& aMargin) const; + void ApplySkipSides(nsMargin& aMargin, + const nsHTMLReflowState* aReflowState = nullptr) const; /** * Like the frame's rect (see |GetRect|), which is the border rect, @@ -2406,8 +2419,16 @@ public: /** * Determine whether borders should not be painted on certain sides of the * frame. + * + * @note (See also bug 743402, comment 11) GetSkipSides() and it's sister + * method, ApplySkipSides() checks to see if this frame has a previous + * or next continuation to determine if a side should be skipped. + * Unfortunately, this only works after reflow has been completed. In + * lieu of this, during reflow, an nsHTMLReflowState parameter can be + * passed in, indicating that it should be used to determine if sides + * should be skipped during reflow. */ - virtual int GetSkipSides() const { return 0; } + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const { return 0; } /** * @returns true if this frame is selected. diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 8d6713be4df8..d55ed165417b 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1771,7 +1771,7 @@ nsImageFrame::List(FILE* out, int32_t aIndent, uint32_t aFlags) const #endif int -nsImageFrame::GetSkipSides() const +nsImageFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const { int skip = 0; if (nullptr != GetPrevInFlow()) { diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 91b5bb5df17a..d982907da171 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -116,7 +116,7 @@ public: void List(FILE* out, int32_t aIndent, uint32_t aFlags = 0) const; #endif - virtual int GetSkipSides() const MOZ_OVERRIDE; + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; nsresult GetIntrinsicImageSize(nsSize& aSize); diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 546c99a3aad0..3368a01abfcd 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -847,7 +847,7 @@ nsInlineFrame::PushFrames(nsPresContext* aPresContext, ////////////////////////////////////////////////////////////////////// int -nsInlineFrame::GetSkipSides() const +nsInlineFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const { int skip = 0; if (!IsLeftMost()) { diff --git a/layout/generic/nsInlineFrame.h b/layout/generic/nsInlineFrame.h index 9dfdc3d84dea..8353fbedda12 100644 --- a/layout/generic/nsInlineFrame.h +++ b/layout/generic/nsInlineFrame.h @@ -136,7 +136,7 @@ protected: nsInlineFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {} - virtual int GetSkipSides() const MOZ_OVERRIDE; + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; nsresult ReflowFrames(nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, diff --git a/layout/generic/nsSplittableFrame.cpp b/layout/generic/nsSplittableFrame.cpp index ed29a3901838..88c7f6fc2614 100644 --- a/layout/generic/nsSplittableFrame.cpp +++ b/layout/generic/nsSplittableFrame.cpp @@ -291,6 +291,43 @@ nsSplittableFrame::ComputeFinalHeight(const nsHTMLReflowState& aReflowState, } } +int +nsSplittableFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const +{ + if (IS_TRUE_OVERFLOW_CONTAINER(this)) { + return (1 << NS_SIDE_TOP) | (1 << NS_SIDE_BOTTOM); + } + + int skip = 0; + + if (GetPrevInFlow()) { + skip |= 1 << NS_SIDE_TOP; + } + + if (aReflowState) { + // We're in the midst of reflow right now, so it's possible that we haven't + // created a nif yet. If our content height is going to exceed our available + // height, though, then we're going to need a next-in-flow, it just hasn't + // been created yet. + + if (NS_UNCONSTRAINEDSIZE != aReflowState->availableHeight) { + nscoord effectiveCH = this->GetEffectiveComputedHeight(*aReflowState); + if (effectiveCH > aReflowState->availableHeight) { + // Our content height is going to exceed our available height, so we're + // going to need a next-in-flow. + skip |= 1 << NS_SIDE_BOTTOM; + } + } + } else { + nsIFrame* nif = GetNextInFlow(); + if (nif && !IS_TRUE_OVERFLOW_CONTAINER(nif)) { + skip |= 1 << NS_SIDE_BOTTOM; + } + } + + return skip; +} + #ifdef DEBUG void nsSplittableFrame::DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, int32_t aIndent) diff --git a/layout/generic/nsSplittableFrame.h b/layout/generic/nsSplittableFrame.h index 13fa523b0235..f1b69318d963 100644 --- a/layout/generic/nsSplittableFrame.h +++ b/layout/generic/nsSplittableFrame.h @@ -118,6 +118,12 @@ protected: nsHTMLReflowMetrics& aMetrics, nscoord aConsumed); + /** + * @see nsIFrame::GetSkipSides() + * @see nsIFrame::ApplySkipSides() + */ + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const; + #ifdef DEBUG virtual void DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, int32_t aIndent) MOZ_OVERRIDE; #endif diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index d68cdacf5479..a9dc53ae8338 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -522,7 +522,7 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, } int -nsTableCellFrame::GetSkipSides() const +nsTableCellFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const { int skip = 0; if (nullptr != GetPrevInFlow()) { diff --git a/layout/tables/nsTableCellFrame.h b/layout/tables/nsTableCellFrame.h index 26ac3a83a56a..c3523c5cae9e 100644 --- a/layout/tables/nsTableCellFrame.h +++ b/layout/tables/nsTableCellFrame.h @@ -221,7 +221,7 @@ public: virtual void InvalidateFrameForRemoval() MOZ_OVERRIDE { InvalidateFrameSubtree(); } protected: - virtual int GetSkipSides() const MOZ_OVERRIDE; + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState= nullptr) const MOZ_OVERRIDE; /** * GetBorderOverflow says how far the cell's own borders extend diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp index 23ee2c48c33b..14f9d6d5d9e2 100644 --- a/layout/tables/nsTableColGroupFrame.cpp +++ b/layout/tables/nsTableColGroupFrame.cpp @@ -337,7 +337,7 @@ nsTableColGroupFrame::RemoveFrame(ChildListID aListID, } int -nsTableColGroupFrame::GetSkipSides() const +nsTableColGroupFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const { int skip = 0; if (nullptr != GetPrevInFlow()) { diff --git a/layout/tables/nsTableColGroupFrame.h b/layout/tables/nsTableColGroupFrame.h index dab5ac59b712..ff5ac05bc275 100644 --- a/layout/tables/nsTableColGroupFrame.h +++ b/layout/tables/nsTableColGroupFrame.h @@ -212,7 +212,7 @@ protected: void InsertColsReflow(int32_t aColIndex, const nsFrameList::Slice& aCols); - virtual int GetSkipSides() const MOZ_OVERRIDE; + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; // data members int32_t mColCount; diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index c6212026fba3..dcb97973d527 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -1332,7 +1332,7 @@ nsTableFrame::PaintTableBorderBackground(nsRenderingContext& aRenderingContext, } int -nsTableFrame::GetSkipSides() const +nsTableFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const { int skip = 0; // frame attribute was accounted for in nsHTMLTableElement::MapTableBorderInto diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 5708e9243da8..8d7ca52dea82 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -509,7 +509,7 @@ protected: void InitChildReflowState(nsHTMLReflowState& aReflowState); - virtual int GetSkipSides() const MOZ_OVERRIDE; + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; public: bool IsRowInserted() const; diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 9f97fab08058..c1e6dba25c70 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -592,7 +592,7 @@ nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, } int -nsTableRowFrame::GetSkipSides() const +nsTableRowFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const { int skip = 0; if (nullptr != GetPrevInFlow()) { diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h index 94df40a00fcd..b9729d100837 100644 --- a/layout/tables/nsTableRowFrame.h +++ b/layout/tables/nsTableRowFrame.h @@ -249,7 +249,7 @@ protected: bool aBorderCollapse, nsTableCellReflowState& aReflowState); - virtual int GetSkipSides() const MOZ_OVERRIDE; + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; // row-specific methods diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index cc9dc5c38faf..c984782e34a9 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -244,7 +244,7 @@ nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, } int -nsTableRowGroupFrame::GetSkipSides() const +nsTableRowGroupFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const { int skip = 0; if (nullptr != GetPrevInFlow()) { diff --git a/layout/tables/nsTableRowGroupFrame.h b/layout/tables/nsTableRowGroupFrame.h index c2a9125b902d..2631ef5e7608 100644 --- a/layout/tables/nsTableRowGroupFrame.h +++ b/layout/tables/nsTableRowGroupFrame.h @@ -343,7 +343,7 @@ protected: bool aBorderCollapse, nsHTMLReflowState& aReflowState); - virtual int GetSkipSides() const MOZ_OVERRIDE; + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; void PlaceChild(nsPresContext* aPresContext, nsRowGroupReflowState& aReflowState,