author | Xidorn Quan <quanxunzhen@gmail.com> |
Wed, 11 Mar 2015 10:28:21 +1100 | |
changeset 232888 | f672b2cd7a4f89c6e91aa62d2e758fff62fbbaa6 |
parent 232887 | a71446331ce6bbaf195f70a84774d3827402ef4d |
child 232889 | 144ea3057b66c0422c3a307bb97fe32250104257 |
push id | 56673 |
push user | xquan@mozilla.com |
push date | Tue, 10 Mar 2015 23:30:22 +0000 |
treeherder | mozilla-inbound@144ea3057b66 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dbaron |
bugs | 1140264 |
milestone | 39.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -3018,19 +3018,19 @@ ElementRestyler::ComputeRestyleResultFro if (oldContext->HasPseudoElementData() != aNewContext->HasPseudoElementData()) { LOG_RESTYLE_CONTINUE("NS_STYLE_HAS_PSEUDO_ELEMENT_DATA differs between old" " and new style contexts"); return eRestyleResult_Continue; } - if (oldContext->IsInlineDescendantOfRuby() != - aNewContext->IsInlineDescendantOfRuby()) { - LOG_RESTYLE_CONTINUE("NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY differes" + if (oldContext->ShouldSuppressLineBreak() != + aNewContext->ShouldSuppressLineBreak()) { + LOG_RESTYLE_CONTINUE("NS_STYLE_SUPPRESS_LINEBREAK differes" "between old and new style contexts"); return eRestyleResult_Continue; } return eRestyleResult_Stop; } ElementRestyler::RestyleResult
--- a/layout/generic/nsBRFrame.cpp +++ b/layout/generic/nsBRFrame.cpp @@ -92,17 +92,17 @@ BRFrame::Reflow(nsPresContext* aPresCont // mode by nsLineLayout::VerticalAlignFrames . // However, it's not always 0. See below. finalSize.ISize(wm) = 0; aMetrics.SetBlockStartAscent(0); // Only when the BR is operating in a line-layout situation will it // behave like a BR. BR is suppressed when it is inside ruby frames. nsLineLayout* ll = aReflowState.mLineLayout; - if (ll && !StyleContext()->IsInlineDescendantOfRuby()) { + if (ll && !StyleContext()->ShouldSuppressLineBreak()) { // Note that the compatibility mode check excludes AlmostStandards // mode, since this is the inline box model. See bug 161691. if ( ll->LineIsEmpty() || aPresContext->CompatibilityMode() == eCompatibility_FullStandards ) { // The line is logically empty; any whitespace is trimmed away. // // If this frame is going to terminate the line we know // that nothing else will go on the line. Therefore, in this @@ -159,26 +159,26 @@ BRFrame::Reflow(nsPresContext* aPresCont NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); } /* virtual */ void BRFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext, nsIFrame::InlineMinISizeData *aData) { - if (!StyleContext()->IsInlineDescendantOfRuby()) { + if (!StyleContext()->ShouldSuppressLineBreak()) { aData->ForceBreak(aRenderingContext); } } /* virtual */ void BRFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext, nsIFrame::InlinePrefISizeData *aData) { - if (!StyleContext()->IsInlineDescendantOfRuby()) { + if (!StyleContext()->ShouldSuppressLineBreak()) { aData->ForceBreak(aRenderingContext); } } /* virtual */ nscoord BRFrame::GetMinISize(nsRenderingContext *aRenderingContext) { nscoord result = 0;
--- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -3924,17 +3924,17 @@ nsFrame::GetPrefISize(nsRenderingContext /* virtual */ void nsFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext, nsIFrame::InlineMinISizeData *aData) { NS_ASSERTION(GetParent(), "Must have a parent if we get here!"); nsIFrame* parent = GetParent(); bool canBreak = !CanContinueTextRun() && - !parent->StyleContext()->IsInlineDescendantOfRuby() && + !parent->StyleContext()->ShouldSuppressLineBreak() && parent->StyleText()->WhiteSpaceCanWrap(parent); if (canBreak) aData->OptionallyBreak(aRenderingContext); aData->trailingWhitespace = 0; aData->skipWhitespace = false; aData->trailingTextFrame = nullptr; aData->currentLine += nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
--- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -452,17 +452,17 @@ nsLineLayout::BeginSpan(nsIFrame* aFrame psd->mIStart = aIStart; psd->mICoord = aIStart; psd->mIEnd = aIEnd; psd->mBaseline = aBaseline; nsIFrame* frame = aSpanReflowState->frame; psd->mNoWrap = !frame->StyleText()->WhiteSpaceCanWrap(frame) || mSuppressLineWrap || - frame->StyleContext()->IsInlineDescendantOfRuby(); + frame->StyleContext()->ShouldSuppressLineBreak(); psd->mWritingMode = aSpanReflowState->GetWritingMode(); // Switch to new span mCurrentSpan = psd; mSpanDepth++; } nscoord @@ -2891,17 +2891,17 @@ nsLineLayout::ApplyFrameJustification(Pe } } return deltaICoord; } static nsIFrame* FindNearestRubyBaseAncestor(nsIFrame* aFrame) { - MOZ_ASSERT(aFrame->StyleContext()->IsInlineDescendantOfRuby()); + MOZ_ASSERT(aFrame->StyleContext()->ShouldSuppressLineBreak()); while (aFrame && aFrame->GetType() != nsGkAtoms::rubyBaseFrame) { aFrame = aFrame->GetParent(); } // XXX It is possible that no ruby base ancestor is found because of // some edge cases like form control or canvas inside ruby text. // See bug 1138092 comment 4. NS_ASSERTION(aFrame, "No ruby base ancestor?"); return aFrame; @@ -3066,26 +3066,26 @@ nsLineLayout::TextAlignLine(nsLineBox* a int32_t additionalGaps = 0; if (!isSVG && (mHasRuby || (doTextAlign && textAlign == NS_STYLE_TEXT_ALIGN_JUSTIFY))) { JustificationComputationState computeState; ComputeFrameJustification(psd, computeState); if (mHasRuby && computeState.mFirstParticipant) { PerFrameData* firstFrame = computeState.mFirstParticipant; - if (firstFrame->mFrame->StyleContext()->IsInlineDescendantOfRuby()) { + if (firstFrame->mFrame->StyleContext()->ShouldSuppressLineBreak()) { MOZ_ASSERT(!firstFrame->mJustificationAssignment.mGapsAtStart); nsIFrame* rubyBase = FindNearestRubyBaseAncestor(firstFrame->mFrame); if (rubyBase && IsRubyAlignSpaceAround(rubyBase)) { firstFrame->mJustificationAssignment.mGapsAtStart = 1; additionalGaps++; } } PerFrameData* lastFrame = computeState.mLastParticipant; - if (lastFrame->mFrame->StyleContext()->IsInlineDescendantOfRuby()) { + if (lastFrame->mFrame->StyleContext()->ShouldSuppressLineBreak()) { MOZ_ASSERT(!lastFrame->mJustificationAssignment.mGapsAtEnd); nsIFrame* rubyBase = FindNearestRubyBaseAncestor(lastFrame->mFrame); if (rubyBase && IsRubyAlignSpaceAround(rubyBase)) { lastFrame->mJustificationAssignment.mGapsAtEnd = 1; additionalGaps++; } } }
--- a/layout/generic/nsRubyBaseContainerFrame.cpp +++ b/layout/generic/nsRubyBaseContainerFrame.cpp @@ -245,24 +245,24 @@ LineBreakBefore(nsIFrame* aFrame, return gfxBreakPriority::eNoBreak; } static void GetIsLineBreakAllowed(nsIFrame* aFrame, bool aIsLineBreakable, bool* aAllowInitialLineBreak, bool* aAllowLineBreak) { nsIFrame* parent = aFrame->GetParent(); - bool inNestedRuby = parent->StyleContext()->IsInlineDescendantOfRuby(); + bool lineBreakSuppressed = parent->StyleContext()->ShouldSuppressLineBreak(); // Allow line break between ruby bases when white-space allows, // we are not inside a nested ruby, and there is no span. - bool allowLineBreak = !inNestedRuby && + bool allowLineBreak = !lineBreakSuppressed && aFrame->StyleText()->WhiteSpaceCanWrap(aFrame); bool allowInitialLineBreak = allowLineBreak; if (!aFrame->GetPrevInFlow()) { - allowInitialLineBreak = !inNestedRuby && + allowInitialLineBreak = !lineBreakSuppressed && parent->StyleText()->WhiteSpaceCanWrap(parent); } if (!aIsLineBreakable) { allowInitialLineBreak = false; } *aAllowInitialLineBreak = allowInitialLineBreak; *aAllowLineBreak = allowLineBreak; }
--- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1922,17 +1922,17 @@ BuildTextRunsScanner::BuildTextRunForFra textStyle = f->StyleText(); if (NS_STYLE_TEXT_TRANSFORM_NONE != textStyle->mTextTransform) { anyTextTransformStyle = true; } textFlags |= GetSpacingFlags(LetterSpacing(f)); textFlags |= GetSpacingFlags(WordSpacing(f)); nsTextFrameUtils::CompressionMode compression = CSSWhitespaceToCompressionMode[textStyle->mWhiteSpace]; - if ((enabledJustification || f->StyleContext()->IsInlineDescendantOfRuby()) && + if ((enabledJustification || f->StyleContext()->ShouldSuppressLineBreak()) && !textStyle->WhiteSpaceIsSignificant() && !isSVG) { textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING; } fontStyle = f->StyleFont(); nsIFrame* parent = mLineContainer->GetParent(); if (NS_MATHML_MATHVARIANT_NONE != fontStyle->mMathVariant) { if (NS_MATHML_MATHVARIANT_NORMAL != fontStyle->mMathVariant) { anyMathMLStyling = true; @@ -2798,17 +2798,17 @@ static int32_t FindChar(const nsTextFrag return (static_cast<const char*>(p) - str) + aOffset; } } return -1; } static bool IsChineseOrJapanese(nsIFrame* aFrame) { - if (aFrame->StyleContext()->IsInlineDescendantOfRuby()) { + if (aFrame->StyleContext()->ShouldSuppressLineBreak()) { // Always treat ruby as CJ language so that those characters can // be expanded properly even when surrounded by other language. return true; } nsIAtom* language = aFrame->StyleFont()->mLanguage; if (!language) { return false; @@ -8290,17 +8290,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL gfxFloat trimmedWidth = 0; gfxFloat availWidth = aAvailableWidth; bool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant() || (GetStateBits() & TEXT_IS_IN_TOKEN_MATHML); int32_t unusedOffset; gfxBreakPriority breakPriority; aLineLayout.GetLastOptionalBreakPosition(&unusedOffset, &breakPriority); gfxTextRun::SuppressBreak suppressBreak = gfxTextRun::eNoSuppressBreak; - if (StyleContext()->IsInlineDescendantOfRuby()) { + if (StyleContext()->ShouldSuppressLineBreak()) { suppressBreak = gfxTextRun::eSuppressAllBreaks; } else if (!aLineLayout.LineIsBreakable()) { suppressBreak = gfxTextRun::eSuppressInitialBreak; } uint32_t transformedCharsFit = mTextRun->BreakAndMeasureText(transformedOffset, transformedLength, (GetStateBits() & TEXT_START_OF_LINE) != 0, availWidth, @@ -8501,17 +8501,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL aLineLayout.NotifyOptionalBreakPosition(this, length, fits, gfxBreakPriority::eNormalBreak); } bool breakAfter = forceBreakAfter; // length == 0 means either the text is empty or it's all collapsed away bool emptyTextAtStartOfLine = atStartOfLine && length == 0; if (!breakAfter && charsFit == length && !emptyTextAtStartOfLine && transformedOffset + transformedLength == mTextRun->GetLength() && - !StyleContext()->IsInlineDescendantOfRuby() && + !StyleContext()->ShouldSuppressLineBreak() && (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK)) { // We placed all the text in the textrun and we have a break opportunity at // the end of the textrun. We need to record it because the following // content may not care about nsLineBreaker. // Note that because we didn't break, we can be sure that (thanks to the // code up above) textMetrics.mAdvanceWidth includes the width of any // trailing whitespace. So we need to subtract trimmableWidth here @@ -8563,17 +8563,17 @@ nsTextFrame::ReflowText(nsLineLayout& aL } else if (cachedNewlineOffset) { mContent->DeleteProperty(nsGkAtoms::newline); } // Compute space and letter counts for justification, if required if (!textStyle->WhiteSpaceIsSignificant() && (lineContainer->StyleText()->mTextAlign == NS_STYLE_TEXT_ALIGN_JUSTIFY || lineContainer->StyleText()->mTextAlignLast == NS_STYLE_TEXT_ALIGN_JUSTIFY || - StyleContext()->IsInlineDescendantOfRuby()) && + StyleContext()->ShouldSuppressLineBreak()) && !lineContainer->IsSVGText()) { AddStateBits(TEXT_JUSTIFICATION_ENABLED); provider.ComputeJustification(offset, charsFit); aLineLayout.SetJustificationInfo(provider.GetJustificationInfo()); } SetLength(contentLength, &aLineLayout, ALLOW_FRAME_CREATION_AND_DESTRUCTION);
--- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -511,16 +511,46 @@ nsStyleContext::SetStyle(nsStyleStructID } else { dataSlot = &mCachedInheritedData.mStyleStructs[aSID]; } NS_ASSERTION(!*dataSlot || (mBits & nsCachedStyleData::GetBitForSID(aSID)), "Going to leak style data"); *dataSlot = aStruct; } +static bool +ShouldSuppressLineBreak(const nsStyleDisplay* aStyleDisplay, + const nsStyleContext* aContainerContext, + const nsStyleDisplay* aContainerDisplay) +{ + // The display change should only occur for "in-flow" children + if (aStyleDisplay->IsOutOfFlowStyle()) { + return false; + } + if (aContainerContext->ShouldSuppressLineBreak()) { + // Line break suppressing bit is propagated to any children of line + // participants, which include inline and inline ruby boxes. + if (aContainerDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE || + aContainerDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY || + aContainerDisplay->mDisplay == NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER) { + return true; + } + } + // Any descendant of ruby level containers is non-breakable, but + // the level containers themselves are breakable. We have to check + // the container display type against all ruby display type here + // because any of the ruby boxes could be anonymous. + if (aContainerDisplay->IsRubyDisplayType() && + aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_BASE_CONTAINER && + aStyleDisplay->mDisplay != NS_STYLE_DISPLAY_RUBY_TEXT_CONTAINER) { + return true; + } + return false; +} + void nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup) { // See if we have any text decorations. // First see if our parent has text decorations. If our parent does, then we inherit the bit. if (mParent && mParent->HasTextDecorationLines()) { mBits |= NS_STYLE_HAS_TEXT_DECORATION_LINES; } else { @@ -637,22 +667,18 @@ nsStyleContext::ApplyStyleFixups(bool aS "converted its display value to be block-level...)"); nsStyleDisplay *mutable_display = static_cast<nsStyleDisplay*>(GetUniqueStyleData(eStyleStruct_Display)); mutable_display->mDisplay = displayVal; } } } - // The display change should only occur for "in-flow" children - if (!disp->IsOutOfFlowStyle() && - ((containerDisp->mDisplay == NS_STYLE_DISPLAY_INLINE && - containerContext->IsInlineDescendantOfRuby()) || - containerDisp->IsRubyDisplayType())) { - mBits |= NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY; + if (::ShouldSuppressLineBreak(disp, containerContext, containerDisp)) { + mBits |= NS_STYLE_SUPPRESS_LINEBREAK; uint8_t displayVal = disp->mDisplay; nsRuleNode::EnsureInlineDisplay(displayVal); if (displayVal != disp->mDisplay) { nsStyleDisplay *mutable_display = static_cast<nsStyleDisplay*>(GetUniqueStyleData(eStyleStruct_Display)); mutable_display->mDisplay = displayVal; } }
--- a/layout/style/nsStyleContext.h +++ b/layout/style/nsStyleContext.h @@ -147,21 +147,23 @@ public: nsRuleNode* aRulesIfVisited, bool aRelevantLinkVisited); // Does this style context or any of its ancestors have text // decoration lines? bool HasTextDecorationLines() const { return !!(mBits & NS_STYLE_HAS_TEXT_DECORATION_LINES); } - // Whether this style context or any of its inline-level ancestors - // is directly contained by a ruby box? It is used to inlinize - // block-level descendants and suppress line breaks inside ruby. - bool IsInlineDescendantOfRuby() const - { return !!(mBits & NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY); } + // Whether any line break inside should be suppressed? If this returns + // true, the line should not be broken inside, which means inlines act + // as if nowrap is set, <br> is suppressed, and blocks are inlinized. + // This bit is propogated to all children of line partitipants. It is + // currenlty used by ruby to make its content frames unbreakable. + bool ShouldSuppressLineBreak() const + { return !!(mBits & NS_STYLE_SUPPRESS_LINEBREAK); } // Does this style context represent the style for a pseudo-element or // inherit data from such a style context? Whether this returns true // is equivalent to whether it or any of its ancestors returns // non-null for GetPseudo. bool HasPseudoElementData() const { return !!(mBits & NS_STYLE_HAS_PSEUDO_ELEMENT_DATA); }
--- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -51,18 +51,18 @@ class imgIContainer; #define NS_STYLE_IS_STYLE_IF_VISITED 0x008000000 // See nsStyleContext::UsesGrandancestorStyle #define NS_STYLE_USES_GRANDANCESTOR_STYLE 0x010000000 // See nsStyleContext::IsShared #define NS_STYLE_IS_SHARED 0x020000000 // See nsStyleContext::AssertStructsNotUsedElsewhere // (This bit is currently only used in #ifdef DEBUG code.) #define NS_STYLE_IS_GOING_AWAY 0x040000000 -// See nsStyleContext::IsInlineDescendantOfRuby -#define NS_STYLE_IS_INLINE_DESCENDANT_OF_RUBY 0x080000000 +// See nsStyleContext::ShouldSuppressLineBreak +#define NS_STYLE_SUPPRESS_LINEBREAK 0x080000000 // See nsStyleContext::GetPseudoEnum #define NS_STYLE_CONTEXT_TYPE_SHIFT 32 // Additional bits for nsRuleNode's mDependentBits: #define NS_RULE_NODE_GC_MARK 0x02000000 #define NS_RULE_NODE_USED_DIRECTLY 0x04000000 #define NS_RULE_NODE_IS_IMPORTANT 0x08000000 #define NS_RULE_NODE_LEVEL_MASK 0xf0000000