Bug 1341981 Part 2 - Convert frame completion status to a tri-state enum class.
MozReview-Commit-ID: 8DrGnwoRz7
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -322,19 +322,19 @@ public:
/* Overflow containers are continuation frames that hold overflow. They
* are created when the frame runs out of computed height, but still has
* too much content to fit in the availableHeight. The parent creates a
* continuation as usual, but marks it as NS_FRAME_IS_OVERFLOW_CONTAINER
* and adds it to its next-in-flow's overflow container list, either by
* adding it directly or by putting it in its own excess overflow containers
* list (to be drained by the next-in-flow when it calls
* ReflowOverflowContainerChildren). The parent continues reflow as if
- * the frame was complete once it ran out of computed height, but returns
- * with either the mIncomplete or mOverflowIncomplete bit set in reflow
- * status to request a next-in-flow. The parent's next-in-flow is then
+ * the frame was complete once it ran out of computed height, but returns a
+ * reflow status with either IsIncomplete() or IsOverflowIncomplete() equal
+ * to true to request a next-in-flow. The parent's next-in-flow is then
* responsible for calling ReflowOverflowContainerChildren to (drain and)
* reflow these overflow continuations. Overflow containers do not affect
* other frames' size or position during reflow (but do affect their
* parent's overflow area).
*
* Overflow container continuations are different from normal continuations
* in that
* - more than one child of the frame can have its next-in-flow broken
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -197,76 +197,84 @@ enum nsSpread {
//----------------------------------------------------------------------
// Reflow status returned by the Reflow() methods.
class nsReflowStatus final {
using StyleClear = mozilla::StyleClear;
public:
nsReflowStatus()
: mBreakType(StyleClear::None)
- , mIncomplete(false)
- , mOverflowIncomplete(false)
+ , mCompletion(Completion::FullyComplete)
, mNextInFlowNeedsReflow(false)
, mTruncated(false)
, mInlineBreak(false)
, mInlineBreakAfter(false)
, mFirstLetterComplete(false)
{}
- // Reset all the bit-fields.
+ // Reset all the member variables.
void Reset() {
mBreakType = StyleClear::None;
- mIncomplete = false;
- mOverflowIncomplete = false;
+ mCompletion = Completion::FullyComplete;
mNextInFlowNeedsReflow = false;
mTruncated = false;
mInlineBreak = false;
mInlineBreakAfter = false;
mFirstLetterComplete = false;
}
- // Return true if all flags are cleared.
+ // Return true if all member variables have their default values.
bool IsEmpty() const {
- return (!mIncomplete &&
- !mOverflowIncomplete &&
+ return (IsFullyComplete() &&
!mNextInFlowNeedsReflow &&
!mTruncated &&
!mInlineBreak &&
!mInlineBreakAfter &&
!mFirstLetterComplete);
}
- // mIncomplete bit flag means the frame does not map all its content, and
- // that the parent frame should create a continuing frame. If this bit
- // isn't set, it means the frame does map all its content. This bit is
- // mutually exclusive with mOverflowIncomplete.
+ // There are three possible completion statuses, represented by
+ // mCompletion.
//
- // mOverflowIncomplete bit flag means that the frame has overflow that is
- // not complete, but its own box is complete. (This happens when content
+ // Incomplete means the frame does *not* map all its content, and the
+ // parent frame should create a continuing frame.
+ //
+ // OverflowIncomplete means that the frame has an overflow that is not
+ // complete, but its own box is complete. (This happens when the content
// overflows a fixed-height box.) The reflower should place and size the
- // frame and continue its reflow, but needs to create an overflow
- // container as a continuation for this frame. See nsContainerFrame.h for
- // more information. This bit is mutually exclusive with mIncomplete.
+ // frame and continue its reflow, but it needs to create an overflow
+ // container as a continuation for this frame. See "Overflow containers"
+ // documentation in nsContainerFrame.h for more information.
+ //
+ // FullyComplete means the frame is neither Incomplete nor
+ // OverflowIncomplete. This is the default state for a nsReflowStatus.
//
- // If both mIncomplete and mOverflowIncomplete are not set, the frame is
- // fully complete.
- bool IsComplete() const { return !mIncomplete; }
- bool IsIncomplete() const { return mIncomplete; }
- bool IsOverflowIncomplete() const { return mOverflowIncomplete; }
+ enum class Completion : uint8_t {
+ // The order of the enum values is important, which represents the
+ // precedence when merging.
+ FullyComplete,
+ OverflowIncomplete,
+ Incomplete,
+ };
+
+ bool IsIncomplete() const { return mCompletion == Completion::Incomplete; }
+ bool IsOverflowIncomplete() const {
+ return mCompletion == Completion::OverflowIncomplete;
+ }
bool IsFullyComplete() const {
- return !IsIncomplete() && !IsOverflowIncomplete();
+ return mCompletion == Completion::FullyComplete;
}
+ // Just for convenience; not a distinct state.
+ bool IsComplete() const { return !IsIncomplete(); }
void SetIncomplete() {
- mIncomplete = true;
- mOverflowIncomplete = false;
+ mCompletion = Completion::Incomplete;
}
void SetOverflowIncomplete() {
- mIncomplete = false;
- mOverflowIncomplete = true;
+ mCompletion = Completion::OverflowIncomplete;
}
// mNextInFlowNeedsReflow bit flag means that the next-in-flow is dirty,
// and also needs to be reflowed. This status only makes sense for a frame
// that is not complete, i.e. you wouldn't set mNextInFlowNeedsReflow when
// IsComplete() is true.
bool NextInFlowNeedsReflow() const { return mNextInFlowNeedsReflow; }
void SetNextInFlowNeedsReflow() { mNextInFlowNeedsReflow = true; }
@@ -278,23 +286,28 @@ public:
// be truncated. Doing so would likely cause an infinite loop.
bool IsTruncated() const { return mTruncated; }
void UpdateTruncated(const mozilla::ReflowInput& aReflowInput,
const mozilla::ReflowOutput& aMetrics);
// Merge the frame completion status bits from aStatus into this.
void MergeCompletionStatusFrom(const nsReflowStatus& aStatus)
{
- mIncomplete |= aStatus.mIncomplete;
- mOverflowIncomplete |= aStatus.mOverflowIncomplete;
+ if (mCompletion < aStatus.mCompletion) {
+ mCompletion = aStatus.mCompletion;
+ }
+
+ // These asserts ensure that the mCompletion merging works as we expect.
+ // (Incomplete beats OverflowIncomplete, which beats FullyComplete.)
+ static_assert(Completion::Incomplete > Completion::OverflowIncomplete &&
+ Completion::OverflowIncomplete > Completion::FullyComplete,
+ "mCompletion merging won't work without this!");
+
mNextInFlowNeedsReflow |= aStatus.mNextInFlowNeedsReflow;
mTruncated |= aStatus.mTruncated;
- if (mIncomplete) {
- mOverflowIncomplete = false;
- }
}
// mInlineBreak bit flag means a break is requested.
bool IsInlineBreak() const { return mInlineBreak; }
// Suppose a break is requested. When mInlineBreakAfter is set, the break
// should occur after the frame just reflowed; when mInlineBreakAfter is
// clear, the break should occur before the frame just reflowed.
@@ -322,20 +335,17 @@ public:
// mFirstLetterComplete bit flag means the break was induced by
// completion of a first-letter.
bool FirstLetterComplete() const { return mFirstLetterComplete; }
void SetFirstLetterComplete() { mFirstLetterComplete = true; }
private:
StyleClear mBreakType;
-
- // Frame completion status bit flags.
- bool mIncomplete : 1;
- bool mOverflowIncomplete : 1;
+ Completion mCompletion;
bool mNextInFlowNeedsReflow : 1;
bool mTruncated : 1;
// Inline break status bit flags.
bool mInlineBreak : 1;
bool mInlineBreakAfter : 1;
bool mFirstLetterComplete : 1;
};
@@ -2318,17 +2328,17 @@ public:
* frame the status returned by the Reflow member function.
*
* This call may be invoked many times, while NS_FRAME_IN_REFLOW is set, before
* it is finally called once with a NS_FRAME_REFLOW_COMPLETE value. When called
* with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the
* frame state will be cleared.
*
* XXX This doesn't make sense. If the frame is reflowed but not complete, then
- * the status should have mIncomplete bit set.
+ * the status should have IsIncomplete() equal to true.
* XXX Don't we want the semantics to dictate that we only call this once for
* a given reflow?
*/
virtual void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput,
nsDidReflowStatus aStatus) = 0;
/**