--- a/layout/base/GeckoRestyleManager.cpp
+++ b/layout/base/GeckoRestyleManager.cpp
@@ -1772,17 +1772,17 @@ ElementRestyler::Restyle(nsRestyleHint a
// If we are restyling this frame with eRestyle_Self or weaker hints,
// we restyle children with nsRestyleHint(0). But we pass the
// eRestyle_ForceDescendants flag down too.
nsRestyleHint childRestyleHint =
nsRestyleHint(aRestyleHint & (eRestyle_SomeDescendants |
eRestyle_Subtree |
eRestyle_ForceDescendants));
- RefPtr<nsStyleContext> oldContext = mFrame->StyleContext();
+ RefPtr<GeckoStyleContext> oldContext = mFrame->StyleContext()->AsGecko();
nsTArray<SwapInstruction> swaps;
// TEMPORARY (until bug 918064): Call RestyleSelf for each
// continuation or block-in-inline sibling.
// We must make a single decision on how to process this frame and
// its descendants, yet RestyleSelf might return different RestyleResult
--- a/layout/style/GeckoStyleContext.cpp
+++ b/layout/style/GeckoStyleContext.cpp
@@ -5,16 +5,20 @@
#include "mozilla/GeckoStyleContext.h"
#include "nsStyleConsts.h"
#include "nsStyleStruct.h"
#include "nsPresContext.h"
#include "nsRuleNode.h"
#include "nsStyleContextInlines.h"
+#include "nsIFrame.h"
+#include "nsLayoutUtils.h"
+#include "mozilla/ReflowInput.h"
+#include "RubyUtils.h"
using namespace mozilla;
GeckoStyleContext::GeckoStyleContext(nsStyleContext* aParent,
nsIAtom* aPseudoTag,
CSSPseudoElementType aPseudoType,
already_AddRefed<nsRuleNode> aRuleNode,
bool aSkipParentDisplayBasedStyleFixup)
@@ -230,8 +234,531 @@ GeckoStyleContext::FindChildWithRules(co
AddChild(result);
}
result->mBits |= NS_STYLE_IS_SHARED;
}
return result.forget();
}
+
+
+// This is an evil evil function, since it forces you to alloc your own separate copy of
+// style data! Do not use this function unless you absolutely have to! You should avoid
+// this at all costs! -dwh
+void*
+GeckoStyleContext::GetUniqueStyleData(const nsStyleStructID& aSID)
+{
+ // If we already own the struct and no kids could depend on it, then
+ // just return it. (We leak in this case if there are kids -- and this
+ // function really shouldn't be called for style contexts that could
+ // have kids depending on the data. ClearStyleData would be OK, but
+ // this test for no mChild or mEmptyChild doesn't catch that case.)
+ const void *current = StyleData(aSID);
+ if (!mChild && !mEmptyChild &&
+ !(mBits & nsCachedStyleData::GetBitForSID(aSID)) &&
+ GetCachedStyleData(aSID))
+ return const_cast<void*>(current);
+
+ void* result;
+ nsPresContext *presContext = PresContext();
+ switch (aSID) {
+
+#define UNIQUE_CASE(c_) \
+ case eStyleStruct_##c_: \
+ result = new (presContext) nsStyle##c_( \
+ * static_cast<const nsStyle##c_ *>(current)); \
+ break;
+
+ UNIQUE_CASE(Font)
+ UNIQUE_CASE(Display)
+ UNIQUE_CASE(Text)
+ UNIQUE_CASE(TextReset)
+ UNIQUE_CASE(Visibility)
+
+#undef UNIQUE_CASE
+
+ default:
+ NS_ERROR("Struct type not supported. Please find another way to do this if you can!");
+ return nullptr;
+ }
+
+ SetStyle(aSID, result);
+ mBits &= ~static_cast<uint64_t>(nsCachedStyleData::GetBitForSID(aSID));
+
+ return result;
+}
+
+
+// This is an evil function, but less evil than GetUniqueStyleData. It
+// creates an empty style struct for this nsStyleContext.
+void*
+GeckoStyleContext::CreateEmptyStyleData(const nsStyleStructID& aSID)
+{
+ MOZ_ASSERT(!mChild && !mEmptyChild &&
+ !(mBits & nsCachedStyleData::GetBitForSID(aSID)) &&
+ !GetCachedStyleData(aSID),
+ "This style should not have been computed");
+
+ void* result;
+ nsPresContext* presContext = PresContext();
+ switch (aSID) {
+#define UNIQUE_CASE(c_) \
+ case eStyleStruct_##c_: \
+ result = new (presContext) nsStyle##c_(presContext); \
+ break;
+
+ UNIQUE_CASE(Border)
+ UNIQUE_CASE(Padding)
+
+#undef UNIQUE_CASE
+
+ default:
+ NS_ERROR("Struct type not supported.");
+ return nullptr;
+ }
+
+ // The new struct is owned by this style context, but that we don't
+ // need to clear the bit in mBits because we've asserted that at the
+ // top of this function.
+ SetStyle(aSID, result);
+ return result;
+}
+
+
+void
+GeckoStyleContext::SetIneligibleForSharing()
+{
+ if (mBits & NS_STYLE_INELIGIBLE_FOR_SHARING) {
+ return;
+ }
+ mBits |= NS_STYLE_INELIGIBLE_FOR_SHARING;
+ if (mChild) {
+ GeckoStyleContext* child = mChild;
+ do {
+ child->SetIneligibleForSharing();
+ child = child->mNextSibling;
+ } while (mChild != child);
+ }
+ if (mEmptyChild) {
+ GeckoStyleContext* child = mEmptyChild;
+ do {
+ child->SetIneligibleForSharing();
+ child = child->mNextSibling;
+ } while (mEmptyChild != child);
+ }
+}
+
+void
+GeckoStyleContext::LogChildStyleContextTree(uint32_t aStructs) const
+{
+ if (nullptr != mChild) {
+ GeckoStyleContext* child = mChild;
+ do {
+ child->LogStyleContextTree(false, aStructs);
+ child = child->mNextSibling;
+ } while (mChild != child);
+ }
+ if (nullptr != mEmptyChild) {
+ GeckoStyleContext* child = mEmptyChild;
+ do {
+ child->LogStyleContextTree(false, aStructs);
+ child = child->mNextSibling;
+ } while (mEmptyChild != child);
+ }
+}
+
+static bool
+ShouldSuppressLineBreak(const nsStyleContext* aContext,
+ const nsStyleDisplay* aDisplay,
+ const nsStyleContext* aParentContext,
+ const nsStyleDisplay* aParentDisplay)
+{
+ // The display change should only occur for "in-flow" children
+ if (aDisplay->IsOutOfFlowStyle()) {
+ return false;
+ }
+ // Display value of any anonymous box should not be touched. In most
+ // cases, anonymous boxes are actually not in ruby frame, but instead,
+ // some other frame with a ruby display value. Non-element pseudos
+ // which represents text frames, as well as ruby pseudos are excluded
+ // because we still want to set the flag for them.
+ if ((aContext->GetPseudoType() == CSSPseudoElementType::InheritingAnonBox ||
+ aContext->GetPseudoType() == CSSPseudoElementType::NonInheritingAnonBox) &&
+ !nsCSSAnonBoxes::IsNonElement(aContext->GetPseudo()) &&
+ !RubyUtils::IsRubyPseudo(aContext->GetPseudo())) {
+ return false;
+ }
+ if (aParentContext->ShouldSuppressLineBreak()) {
+ // Line break suppressing bit is propagated to any children of
+ // line participants, which include inline, contents, and inline
+ // ruby boxes.
+ if (aParentDisplay->mDisplay == mozilla::StyleDisplay::Inline ||
+ aParentDisplay->mDisplay == mozilla::StyleDisplay::Contents ||
+ aParentDisplay->mDisplay == mozilla::StyleDisplay::Ruby ||
+ aParentDisplay->mDisplay == mozilla::StyleDisplay::RubyBaseContainer) {
+ 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.
+ // Note that, when certain HTML tags, e.g. form controls, have ruby
+ // level container display type, they could also escape from this flag
+ // while they shouldn't. However, it is generally fine since they
+ // won't usually break the assertion that there is no line break
+ // inside ruby, because:
+ // 1. their display types, the ruby level container types, are inline-
+ // outside, which means they won't cause any forced line break; and
+ // 2. they never start an inline span, which means their children, if
+ // any, won't be able to break the line its ruby ancestor lays; and
+ // 3. their parent frame is always a ruby content frame (due to
+ // anonymous ruby box generation), which makes line layout suppress
+ // any optional line break around this frame.
+ // However, there is one special case which is BR tag, because it
+ // directly affects the line layout. This case is handled by the BR
+ // frame which checks the flag of its parent frame instead of itself.
+ if ((aParentDisplay->IsRubyDisplayType() &&
+ aDisplay->mDisplay != mozilla::StyleDisplay::RubyBaseContainer &&
+ aDisplay->mDisplay != mozilla::StyleDisplay::RubyTextContainer) ||
+ // Since ruby base and ruby text may exist themselves without any
+ // non-anonymous frame outside, we should also check them.
+ aDisplay->mDisplay == mozilla::StyleDisplay::RubyBase ||
+ aDisplay->mDisplay == mozilla::StyleDisplay::RubyText) {
+ return true;
+ }
+ return false;
+}
+
+void
+nsStyleContext::SetStyleBits()
+{
+ // Here we set up various style bits for both the Gecko and Servo paths.
+ // _Only_ change the bits here. For fixups of the computed values, you can
+ // add to ApplyStyleFixups in Gecko and StyleAdjuster as part of Servo's
+ // cascade.
+
+ // 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()) {
+ AddStyleBit(NS_STYLE_HAS_TEXT_DECORATION_LINES);
+ } else {
+ // We might have defined a decoration.
+ if (StyleTextReset()->HasTextDecorationLines()) {
+ AddStyleBit(NS_STYLE_HAS_TEXT_DECORATION_LINES);
+ }
+ }
+
+ if ((mParent && mParent->HasPseudoElementData()) || IsPseudoElement()) {
+ AddStyleBit(NS_STYLE_HAS_PSEUDO_ELEMENT_DATA);
+ }
+
+ // Set the NS_STYLE_IN_DISPLAY_NONE_SUBTREE bit
+ const nsStyleDisplay* disp = StyleDisplay();
+ if ((mParent && mParent->IsInDisplayNoneSubtree()) ||
+ disp->mDisplay == mozilla::StyleDisplay::None) {
+ AddStyleBit(NS_STYLE_IN_DISPLAY_NONE_SUBTREE);
+ }
+
+ // Mark text combined for text-combine-upright, as needed.
+ if (mPseudoTag == nsCSSAnonBoxes::mozText && mParent &&
+ mParent->StyleVisibility()->mWritingMode !=
+ NS_STYLE_WRITING_MODE_HORIZONTAL_TB &&
+ mParent->StyleText()->mTextCombineUpright ==
+ NS_STYLE_TEXT_COMBINE_UPRIGHT_ALL) {
+ AddStyleBit(NS_STYLE_IS_TEXT_COMBINED);
+ }
+}
+
+// Flex & grid containers blockify their children.
+// "The display value of a flex item is blockified"
+// https://drafts.csswg.org/css-flexbox-1/#flex-items
+// "The display value of a grid item is blockified"
+// https://drafts.csswg.org/css-grid/#grid-items
+static bool
+ShouldBlockifyChildren(const nsStyleDisplay* aStyleDisp)
+{
+ auto displayVal = aStyleDisp->mDisplay;
+ return mozilla::StyleDisplay::Flex == displayVal ||
+ mozilla::StyleDisplay::InlineFlex == displayVal ||
+ mozilla::StyleDisplay::Grid == displayVal ||
+ mozilla::StyleDisplay::InlineGrid == displayVal;
+}
+
+#ifdef DEBUG
+void
+GeckoStyleContext::AssertChildStructsNotUsedElsewhere(nsStyleContext* aDestroyingContext,
+ int32_t aLevels) const
+{
+ if (mChild) {
+ const GeckoStyleContext* child = mChild;
+ do {
+ child->AssertStructsNotUsedElsewhere(aDestroyingContext, aLevels - 1);
+ child = child->mNextSibling;
+ } while (child != mChild);
+ }
+
+ if (mEmptyChild) {
+ const GeckoStyleContext* child = mEmptyChild;
+ do {
+ child->AssertStructsNotUsedElsewhere(aDestroyingContext, aLevels - 1);
+ child = child->mNextSibling;
+ } while (child != mEmptyChild);
+ }
+}
+#endif
+
+void
+GeckoStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup)
+{
+ MOZ_ASSERT(!mSource.IsServoComputedValues(),
+ "Can't do Gecko style fixups on Servo values");
+
+#define GET_UNIQUE_STYLE_DATA(name_) \
+ static_cast<nsStyle##name_*>(GetUniqueStyleData(eStyleStruct_##name_))
+
+ // CSS Inline Layout Level 3 - 3.5 Sizing Initial Letters:
+ // For an N-line drop initial in a Western script, the cap-height of the
+ // letter needs to be (N – 1) times the line-height, plus the cap-height
+ // of the surrounding text.
+ if (mPseudoTag == nsCSSPseudoElements::firstLetter) {
+ const nsStyleTextReset* textReset = StyleTextReset();
+ if (textReset->mInitialLetterSize != 0.0f) {
+ nsStyleContext* containerSC = mParent;
+ const nsStyleDisplay* containerDisp = containerSC->StyleDisplay();
+ while (containerDisp->mDisplay == mozilla::StyleDisplay::Contents) {
+ if (!containerSC->GetParent()) {
+ break;
+ }
+ containerSC = containerSC->GetParent();
+ containerDisp = containerSC->StyleDisplay();
+ }
+ nscoord containerLH =
+ ReflowInput::CalcLineHeight(nullptr, containerSC, NS_AUTOHEIGHT, 1.0f);
+ RefPtr<nsFontMetrics> containerFM =
+ nsLayoutUtils::GetFontMetricsForStyleContext(containerSC);
+ MOZ_ASSERT(containerFM, "Should have fontMetrics!!");
+ nscoord containerCH = containerFM->CapHeight();
+ RefPtr<nsFontMetrics> firstLetterFM =
+ nsLayoutUtils::GetFontMetricsForStyleContext(this);
+ MOZ_ASSERT(firstLetterFM, "Should have fontMetrics!!");
+ nscoord firstLetterCH = firstLetterFM->CapHeight();
+ nsStyleFont* mutableStyleFont = GET_UNIQUE_STYLE_DATA(Font);
+ float invCapHeightRatio =
+ mutableStyleFont->mFont.size / NSCoordToFloat(firstLetterCH);
+ mutableStyleFont->mFont.size =
+ NSToCoordRound(((textReset->mInitialLetterSize - 1) * containerLH +
+ containerCH) *
+ invCapHeightRatio);
+ }
+ }
+
+ // Change writing mode of text frame for text-combine-upright. We use
+ // style structs of the parent to avoid triggering computation before
+ // we change the writing mode.
+ // It is safe to look at the parent's style because we are looking at
+ // inherited properties, and ::-moz-text never matches any rules.
+ if (mPseudoTag == nsCSSAnonBoxes::mozText && mParent &&
+ mParent->StyleVisibility()->mWritingMode !=
+ NS_STYLE_WRITING_MODE_HORIZONTAL_TB &&
+ mParent->StyleText()->mTextCombineUpright ==
+ NS_STYLE_TEXT_COMBINE_UPRIGHT_ALL) {
+ MOZ_ASSERT(!PeekStyleVisibility(), "If StyleVisibility was already "
+ "computed, some properties may have been computed "
+ "incorrectly based on the old writing mode value");
+ nsStyleVisibility* mutableVis = GET_UNIQUE_STYLE_DATA(Visibility);
+ mutableVis->mWritingMode = NS_STYLE_WRITING_MODE_HORIZONTAL_TB;
+ }
+
+ // CSS 2.1 10.1: Propagate the root element's 'direction' to the ICB.
+ // (PageContentFrame/CanvasFrame etc will inherit 'direction')
+ if (mPseudoTag == nsCSSAnonBoxes::viewport) {
+ nsPresContext* presContext = PresContext();
+ mozilla::dom::Element* docElement = presContext->Document()->GetRootElement();
+ if (docElement) {
+ RefPtr<nsStyleContext> rootStyle =
+ presContext->StyleSet()->AsGecko()->ResolveStyleFor(docElement, nullptr);
+ auto dir = rootStyle->StyleVisibility()->mDirection;
+ if (dir != StyleVisibility()->mDirection) {
+ nsStyleVisibility* uniqueVisibility = GET_UNIQUE_STYLE_DATA(Visibility);
+ uniqueVisibility->mDirection = dir;
+ }
+ }
+ }
+
+ // Correct tables.
+ const nsStyleDisplay* disp = StyleDisplay();
+ if (disp->mDisplay == mozilla::StyleDisplay::Table) {
+ // -moz-center and -moz-right are used for HTML's alignment
+ // This is covering the <div align="right"><table>...</table></div> case.
+ // In this case, we don't want to inherit the text alignment into the table.
+ const nsStyleText* text = StyleText();
+
+ if (text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_LEFT ||
+ text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
+ text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)
+ {
+ nsStyleText* uniqueText = GET_UNIQUE_STYLE_DATA(Text);
+ uniqueText->mTextAlign = NS_STYLE_TEXT_ALIGN_START;
+ }
+ }
+
+ // CSS2.1 section 9.2.4 specifies fixups for the 'display' property of
+ // the root element. We can't implement them in nsRuleNode because we
+ // don't want to store all display structs that aren't 'block',
+ // 'inline', or 'table' in the style context tree on the off chance
+ // that the root element has its style reresolved later. So do them
+ // here if needed, by changing the style data, so that other code
+ // doesn't get confused by looking at the style data.
+ if (!mParent &&
+ // We don't want to blockify various anon boxes that just happen to not
+ // inherit from anything. So restrict blockification only to actual
+ // elements, the viewport (which should be block anyway, but in SVG
+ // document's isn't because we lazy-load ua.css there), and the ::backdrop
+ // pseudo-element. This last is explicitly allowed to have any specified
+ // display type in the spec, but computes to a blockified display type per
+ // various provisions of
+ // https://fullscreen.spec.whatwg.org/#new-stacking-layer
+ (!mPseudoTag ||
+ mPseudoTag == nsCSSAnonBoxes::viewport ||
+ mPseudoTag == nsCSSPseudoElements::backdrop)) {
+ auto displayVal = disp->mDisplay;
+ if (displayVal != mozilla::StyleDisplay::Contents) {
+ nsRuleNode::EnsureBlockDisplay(displayVal, true);
+ } else {
+ // http://dev.w3.org/csswg/css-display/#transformations
+ // "... a display-outside of 'contents' computes to block-level
+ // on the root element."
+ displayVal = mozilla::StyleDisplay::Block;
+ }
+ if (displayVal != disp->mDisplay) {
+ nsStyleDisplay* mutable_display = GET_UNIQUE_STYLE_DATA(Display);
+ disp = mutable_display;
+
+ // If we're in this code, then mOriginalDisplay doesn't matter
+ // for purposes of the cascade (because this nsStyleDisplay
+ // isn't living in the ruletree anyway), and for determining
+ // hypothetical boxes it's better to have mOriginalDisplay
+ // matching mDisplay here.
+ mutable_display->mOriginalDisplay = mutable_display->mDisplay =
+ displayVal;
+ }
+ }
+
+ // Adjust the "display" values of flex and grid items (but not for raw text
+ // or placeholders). CSS3 Flexbox section 4 says:
+ // # The computed 'display' of a flex item is determined
+ // # by applying the table in CSS 2.1 Chapter 9.7.
+ // ...which converts inline-level elements to their block-level equivalents.
+ // Any block-level element directly contained by elements with ruby display
+ // values are converted to their inline-level equivalents.
+ if (!aSkipParentDisplayBasedStyleFixup && mParent) {
+ // Skip display:contents ancestors to reach the potential container.
+ // (If there are only display:contents ancestors between this node and
+ // a flex/grid container ancestor, then this node is a flex/grid item, since
+ // its parent *in the frame tree* will be the flex/grid container. So we treat
+ // it like a flex/grid item here.)
+ nsStyleContext* containerContext = mParent;
+ const nsStyleDisplay* containerDisp = containerContext->StyleDisplay();
+ while (containerDisp->mDisplay == mozilla::StyleDisplay::Contents) {
+ if (!containerContext->GetParent()) {
+ break;
+ }
+ containerContext = containerContext->GetParent();
+ containerDisp = containerContext->StyleDisplay();
+ }
+ if (ShouldBlockifyChildren(containerDisp) &&
+ !nsCSSAnonBoxes::IsNonElement(GetPseudo())) {
+ // NOTE: Technically, we shouldn't modify the 'display' value of
+ // positioned elements, since they aren't flex/grid items. However,
+ // we don't need to worry about checking for that, because if we're
+ // positioned, we'll have already been through a call to
+ // EnsureBlockDisplay() in nsRuleNode, so this call here won't change
+ // anything. So we're OK.
+ auto displayVal = disp->mDisplay;
+ nsRuleNode::EnsureBlockDisplay(displayVal);
+ if (displayVal != disp->mDisplay) {
+ NS_ASSERTION(!disp->IsAbsolutelyPositionedStyle(),
+ "We shouldn't be changing the display value of "
+ "positioned content (and we should have already "
+ "converted its display value to be block-level...)");
+ nsStyleDisplay* mutable_display = GET_UNIQUE_STYLE_DATA(Display);
+ disp = mutable_display;
+ mutable_display->mDisplay = displayVal;
+ }
+ }
+ }
+
+ // Note: This must come after the blockification above, otherwise we fail
+ // the grid-item-blockifying-001.html reftest.
+ if (mParent && ::ShouldSuppressLineBreak(this, disp, mParent,
+ mParent->StyleDisplay())) {
+ mBits |= NS_STYLE_SUPPRESS_LINEBREAK;
+ auto displayVal = disp->mDisplay;
+ nsRuleNode::EnsureInlineDisplay(displayVal);
+ if (displayVal != disp->mDisplay) {
+ nsStyleDisplay* mutable_display = GET_UNIQUE_STYLE_DATA(Display);
+ disp = mutable_display;
+ mutable_display->mDisplay = displayVal;
+ }
+ }
+ // Suppress border/padding of ruby level containers
+ if (disp->mDisplay == mozilla::StyleDisplay::RubyBaseContainer ||
+ disp->mDisplay == mozilla::StyleDisplay::RubyTextContainer) {
+ CreateEmptyStyleData(eStyleStruct_Border);
+ CreateEmptyStyleData(eStyleStruct_Padding);
+ }
+ if (disp->IsRubyDisplayType()) {
+ // Per CSS Ruby spec section Bidi Reordering, for all ruby boxes,
+ // the 'normal' and 'embed' values of 'unicode-bidi' should compute to
+ // 'isolate', and 'bidi-override' should compute to 'isolate-override'.
+ const nsStyleTextReset* textReset = StyleTextReset();
+ uint8_t unicodeBidi = textReset->mUnicodeBidi;
+ if (unicodeBidi == NS_STYLE_UNICODE_BIDI_NORMAL ||
+ unicodeBidi == NS_STYLE_UNICODE_BIDI_EMBED) {
+ unicodeBidi = NS_STYLE_UNICODE_BIDI_ISOLATE;
+ } else if (unicodeBidi == NS_STYLE_UNICODE_BIDI_BIDI_OVERRIDE) {
+ unicodeBidi = NS_STYLE_UNICODE_BIDI_ISOLATE_OVERRIDE;
+ }
+ if (unicodeBidi != textReset->mUnicodeBidi) {
+ nsStyleTextReset* mutableTextReset = GET_UNIQUE_STYLE_DATA(TextReset);
+ mutableTextReset->mUnicodeBidi = unicodeBidi;
+ }
+ }
+
+ /*
+ * According to https://drafts.csswg.org/css-writing-modes-3/#block-flow:
+ *
+ * If a box has a different block flow direction than its containing block:
+ * * If the box has a specified display of inline, its display computes
+ * to inline-block. [CSS21]
+ * ...etc.
+ */
+ if (disp->mDisplay == mozilla::StyleDisplay::Inline &&
+ !nsCSSAnonBoxes::IsNonElement(mPseudoTag) &&
+ mParent) {
+ auto cbContext = mParent;
+ while (cbContext->StyleDisplay()->mDisplay == mozilla::StyleDisplay::Contents) {
+ cbContext = cbContext->mParent;
+ }
+ MOZ_ASSERT(cbContext, "the root context can't have display:contents");
+ // We don't need the full mozilla::WritingMode value (incorporating dir
+ // and text-orientation) here; just the writing-mode property is enough.
+ if (StyleVisibility()->mWritingMode !=
+ cbContext->StyleVisibility()->mWritingMode) {
+ nsStyleDisplay* mutable_display = GET_UNIQUE_STYLE_DATA(Display);
+ disp = mutable_display;
+ mutable_display->mOriginalDisplay = mutable_display->mDisplay =
+ mozilla::StyleDisplay::InlineBlock;
+ }
+ }
+
+ // Compute User Interface style, to trigger loads of cursors
+ StyleUserInterface();
+#undef GET_UNIQUE_STYLE_DATA
+}
+
+bool
+GeckoStyleContext::HasNoChildren() const
+{
+ return (nullptr == mChild) && (nullptr == mEmptyChild);
+}
\ No newline at end of file
--- a/layout/style/GeckoStyleContext.h
+++ b/layout/style/GeckoStyleContext.h
@@ -22,16 +22,28 @@ public:
void* operator new(size_t sz, nsPresContext* aPresContext);
nsPresContext* PresContext() const {
return mSource.AsGeckoRuleNode()->PresContext();
}
void AddChild(GeckoStyleContext* aChild);
void RemoveChild(GeckoStyleContext* aChild);
+
+ void* GetUniqueStyleData(const nsStyleStructID& aSID);
+ void* CreateEmptyStyleData(const nsStyleStructID& aSID);
+
+
+ /**
+ * Sets the NS_STYLE_INELIGIBLE_FOR_SHARING bit on this style context
+ * and its descendants. If it finds a descendant that has the bit
+ * already set, assumes that it can skip that subtree.
+ */
+ void SetIneligibleForSharing();
+ void LogChildStyleContextTree(uint32_t aStructs) const;
/**
* On each descendant of this style context, clears out any cached inherited
* structs indicated in aStructs.
*/
void ClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
// Find, if it already exists *and is easily findable* (i.e., near the
// start of the child list), a style context whose:
// * GetPseudo() matches aPseudoTag
@@ -40,21 +52,32 @@ public:
// non-null, GetStyleIfVisited()->mSource == aSourceIfVisited
// * RelevantLinkVisited() == aRelevantLinkVisited
already_AddRefed<GeckoStyleContext>
FindChildWithRules(const nsIAtom* aPseudoTag,
mozilla::NonOwningStyleContextSource aSource,
mozilla::NonOwningStyleContextSource aSourceIfVisited,
bool aRelevantLinkVisited);
+#ifdef DEBUG
+ void AssertChildStructsNotUsedElsewhere(nsStyleContext* aDestroyingContext,
+ int32_t aLevels) const;
+#endif
+
+ // Only called for Gecko-backed nsStyleContexts.
+ void ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup);
+
+ void ListDescendants(FILE* out, int32_t aIndent);
+
+ bool HasNoChildren() const;
+
private:
// Helper for ClearCachedInheritedStyleDataOnDescendants.
void DoClearCachedInheritedStyleDataOnDescendants(uint32_t aStructs);
-public:
- void ListDescendants(FILE* out, int32_t aIndent);
+
// Children are kept in two circularly-linked lists. The list anchor
// is not part of the list (null for empty), and we point to the first
// child.
// mEmptyChild for children whose rule node is the root rule node, and
// mChild for other children. The order of children is not
// meaningful.
GeckoStyleContext* mChild;
GeckoStyleContext* mEmptyChild;
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -124,18 +124,17 @@ nsStyleContext::FinishConstruction()
static_assert(NS_STYLE_INHERIT_MASK & NS_STYLE_INHERIT_BIT(LastItem),
"NS_STYLE_INHERIT_MASK must be bigger, and other bits shifted");
#undef eStyleStruct_LastItem
}
nsStyleContext::~nsStyleContext()
{
if (const GeckoStyleContext* gecko = GetAsGecko()) {
- NS_ASSERTION((nullptr == gecko->mChild) && (nullptr == gecko->mEmptyChild),
- "destructing context with children");
+ NS_ASSERTION(gecko->HasNoChildren(), "destructing context with children");
}
MOZ_ASSERT(!mSource.IsServoComputedValues() || !mCachedResetData);
#ifdef DEBUG
if (mSource.IsServoComputedValues()) {
MOZ_ASSERT(!mCachedResetData,
"Servo shouldn't cache reset structs in nsStyleContext");
for (const auto* data : mCachedInheritedData.mStyleStructs) {
@@ -249,31 +248,17 @@ nsStyleContext::AssertStructsNotUsedElse
#undef STYLE_STRUCT_INHERITED
#undef STYLE_STRUCT_RESET
}
}
}
if (const GeckoStyleContext* gecko = GetAsGecko()) {
- if (gecko->mChild) {
- const GeckoStyleContext* child = gecko->mChild;
- do {
- child->AssertStructsNotUsedElsewhere(aDestroyingContext, aLevels - 1);
- child = child->mNextSibling;
- } while (child != gecko->mChild);
- }
-
- if (gecko->mEmptyChild) {
- const GeckoStyleContext* child = gecko->mEmptyChild;
- do {
- child->AssertStructsNotUsedElsewhere(aDestroyingContext, aLevels - 1);
- child = child->mNextSibling;
- } while (child != gecko->mEmptyChild);
- }
+ gecko->AssertChildStructsNotUsedElsewhere(aDestroyingContext, aLevels - 1);
}
}
#endif
void nsStyleContext::AddChild(nsStyleContext* aChild)
{
if (GeckoStyleContext* gecko = GetAsGecko()) {
@@ -377,107 +362,16 @@ const void* nsStyleContext::StyleData(ns
// potentially giving mCachedInheritedData the same treatment.
//
// Note that there is a similar comment in the struct getters in nsStyleContext.h.
SetStyle(aSID, const_cast<void*>(newData));
}
return newData;
}
-// This is an evil evil function, since it forces you to alloc your own separate copy of
-// style data! Do not use this function unless you absolutely have to! You should avoid
-// this at all costs! -dwh
-void*
-nsStyleContext::GetUniqueStyleData(const nsStyleStructID& aSID)
-{
- MOZ_ASSERT(!mSource.IsServoComputedValues(),
- "Can't COW-mutate servo values from Gecko!");
-
- // If we already own the struct and no kids could depend on it, then
- // just return it. (We leak in this case if there are kids -- and this
- // function really shouldn't be called for style contexts that could
- // have kids depending on the data. ClearStyleData would be OK, but
- // this test for no mChild or mEmptyChild doesn't catch that case.)
- const void *current = StyleData(aSID);
- GeckoStyleContext *child = nullptr, *emptyChild = nullptr;
- if (const GeckoStyleContext* gecko = GetAsGecko()) {
- child = gecko->mChild;
- emptyChild = gecko->mEmptyChild;
- }
- if (!child && !emptyChild &&
- !(mBits & nsCachedStyleData::GetBitForSID(aSID)) &&
- GetCachedStyleData(aSID))
- return const_cast<void*>(current);
-
- void* result;
- nsPresContext *presContext = PresContext();
- switch (aSID) {
-
-#define UNIQUE_CASE(c_) \
- case eStyleStruct_##c_: \
- result = new (presContext) nsStyle##c_( \
- * static_cast<const nsStyle##c_ *>(current)); \
- break;
-
- UNIQUE_CASE(Font)
- UNIQUE_CASE(Display)
- UNIQUE_CASE(Text)
- UNIQUE_CASE(TextReset)
- UNIQUE_CASE(Visibility)
-
-#undef UNIQUE_CASE
-
- default:
- NS_ERROR("Struct type not supported. Please find another way to do this if you can!");
- return nullptr;
- }
-
- SetStyle(aSID, result);
- mBits &= ~static_cast<uint64_t>(nsCachedStyleData::GetBitForSID(aSID));
-
- return result;
-}
-
-// This is an evil function, but less evil than GetUniqueStyleData. It
-// creates an empty style struct for this nsStyleContext.
-void*
-nsStyleContext::CreateEmptyStyleData(const nsStyleStructID& aSID)
-{
- if (const GeckoStyleContext* gecko = GetAsGecko()) {
- MOZ_ASSERT(!gecko->mChild && !gecko->mEmptyChild, "This style should not have been computed");
- }
- MOZ_ASSERT(!(mBits & nsCachedStyleData::GetBitForSID(aSID)) &&
- !GetCachedStyleData(aSID),
- "This style should not have been computed");
-
- void* result;
- nsPresContext* presContext = PresContext();
- switch (aSID) {
-#define UNIQUE_CASE(c_) \
- case eStyleStruct_##c_: \
- result = new (presContext) nsStyle##c_(presContext); \
- break;
-
- UNIQUE_CASE(Border)
- UNIQUE_CASE(Padding)
-
-#undef UNIQUE_CASE
-
- default:
- NS_ERROR("Struct type not supported.");
- return nullptr;
- }
-
- // The new struct is owned by this style context, but that we don't
- // need to clear the bit in mBits because we've asserted that at the
- // top of this function.
- SetStyle(aSID, result);
- return result;
-}
-
void
nsStyleContext::SetStyle(nsStyleStructID aSID, void* aStruct)
{
MOZ_ASSERT(!mSource.IsServoComputedValues(),
"Servo shouldn't cache style structs in the style context!");
// This method should only be called from nsRuleNode! It is not a public
// method!
@@ -496,384 +390,16 @@ 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 nsStyleContext* aContext,
- const nsStyleDisplay* aDisplay,
- const nsStyleContext* aParentContext,
- const nsStyleDisplay* aParentDisplay)
-{
- // The display change should only occur for "in-flow" children
- if (aDisplay->IsOutOfFlowStyle()) {
- return false;
- }
- // Display value of any anonymous box should not be touched. In most
- // cases, anonymous boxes are actually not in ruby frame, but instead,
- // some other frame with a ruby display value. Non-element pseudos
- // which represents text frames, as well as ruby pseudos are excluded
- // because we still want to set the flag for them.
- if ((aContext->GetPseudoType() == CSSPseudoElementType::InheritingAnonBox ||
- aContext->GetPseudoType() == CSSPseudoElementType::NonInheritingAnonBox) &&
- !nsCSSAnonBoxes::IsNonElement(aContext->GetPseudo()) &&
- !RubyUtils::IsRubyPseudo(aContext->GetPseudo())) {
- return false;
- }
- if (aParentContext->ShouldSuppressLineBreak()) {
- // Line break suppressing bit is propagated to any children of
- // line participants, which include inline, contents, and inline
- // ruby boxes.
- if (aParentDisplay->mDisplay == mozilla::StyleDisplay::Inline ||
- aParentDisplay->mDisplay == mozilla::StyleDisplay::Contents ||
- aParentDisplay->mDisplay == mozilla::StyleDisplay::Ruby ||
- aParentDisplay->mDisplay == mozilla::StyleDisplay::RubyBaseContainer) {
- 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.
- // Note that, when certain HTML tags, e.g. form controls, have ruby
- // level container display type, they could also escape from this flag
- // while they shouldn't. However, it is generally fine since they
- // won't usually break the assertion that there is no line break
- // inside ruby, because:
- // 1. their display types, the ruby level container types, are inline-
- // outside, which means they won't cause any forced line break; and
- // 2. they never start an inline span, which means their children, if
- // any, won't be able to break the line its ruby ancestor lays; and
- // 3. their parent frame is always a ruby content frame (due to
- // anonymous ruby box generation), which makes line layout suppress
- // any optional line break around this frame.
- // However, there is one special case which is BR tag, because it
- // directly affects the line layout. This case is handled by the BR
- // frame which checks the flag of its parent frame instead of itself.
- if ((aParentDisplay->IsRubyDisplayType() &&
- aDisplay->mDisplay != mozilla::StyleDisplay::RubyBaseContainer &&
- aDisplay->mDisplay != mozilla::StyleDisplay::RubyTextContainer) ||
- // Since ruby base and ruby text may exist themselves without any
- // non-anonymous frame outside, we should also check them.
- aDisplay->mDisplay == mozilla::StyleDisplay::RubyBase ||
- aDisplay->mDisplay == mozilla::StyleDisplay::RubyText) {
- return true;
- }
- return false;
-}
-
-// Flex & grid containers blockify their children.
-// "The display value of a flex item is blockified"
-// https://drafts.csswg.org/css-flexbox-1/#flex-items
-// "The display value of a grid item is blockified"
-// https://drafts.csswg.org/css-grid/#grid-items
-static bool
-ShouldBlockifyChildren(const nsStyleDisplay* aStyleDisp)
-{
- auto displayVal = aStyleDisp->mDisplay;
- return mozilla::StyleDisplay::Flex == displayVal ||
- mozilla::StyleDisplay::InlineFlex == displayVal ||
- mozilla::StyleDisplay::Grid == displayVal ||
- mozilla::StyleDisplay::InlineGrid == displayVal;
-}
-
-void
-nsStyleContext::SetStyleBits()
-{
- // Here we set up various style bits for both the Gecko and Servo paths.
- // _Only_ change the bits here. For fixups of the computed values, you can
- // add to ApplyStyleFixups in Gecko and StyleAdjuster as part of Servo's
- // cascade.
-
- // 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()) {
- AddStyleBit(NS_STYLE_HAS_TEXT_DECORATION_LINES);
- } else {
- // We might have defined a decoration.
- if (StyleTextReset()->HasTextDecorationLines()) {
- AddStyleBit(NS_STYLE_HAS_TEXT_DECORATION_LINES);
- }
- }
-
- if ((mParent && mParent->HasPseudoElementData()) || IsPseudoElement()) {
- AddStyleBit(NS_STYLE_HAS_PSEUDO_ELEMENT_DATA);
- }
-
- // Set the NS_STYLE_IN_DISPLAY_NONE_SUBTREE bit
- const nsStyleDisplay* disp = StyleDisplay();
- if ((mParent && mParent->IsInDisplayNoneSubtree()) ||
- disp->mDisplay == mozilla::StyleDisplay::None) {
- AddStyleBit(NS_STYLE_IN_DISPLAY_NONE_SUBTREE);
- }
-
- // Mark text combined for text-combine-upright, as needed.
- if (mPseudoTag == nsCSSAnonBoxes::mozText && mParent &&
- mParent->StyleVisibility()->mWritingMode !=
- NS_STYLE_WRITING_MODE_HORIZONTAL_TB &&
- mParent->StyleText()->mTextCombineUpright ==
- NS_STYLE_TEXT_COMBINE_UPRIGHT_ALL) {
- AddStyleBit(NS_STYLE_IS_TEXT_COMBINED);
- }
-}
-
-void
-nsStyleContext::ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup)
-{
- MOZ_ASSERT(!mSource.IsServoComputedValues(),
- "Can't do Gecko style fixups on Servo values");
-
-#define GET_UNIQUE_STYLE_DATA(name_) \
- static_cast<nsStyle##name_*>(GetUniqueStyleData(eStyleStruct_##name_))
-
- // CSS Inline Layout Level 3 - 3.5 Sizing Initial Letters:
- // For an N-line drop initial in a Western script, the cap-height of the
- // letter needs to be (N – 1) times the line-height, plus the cap-height
- // of the surrounding text.
- if (mPseudoTag == nsCSSPseudoElements::firstLetter) {
- const nsStyleTextReset* textReset = StyleTextReset();
- if (textReset->mInitialLetterSize != 0.0f) {
- nsStyleContext* containerSC = mParent;
- const nsStyleDisplay* containerDisp = containerSC->StyleDisplay();
- while (containerDisp->mDisplay == mozilla::StyleDisplay::Contents) {
- if (!containerSC->GetParent()) {
- break;
- }
- containerSC = containerSC->GetParent();
- containerDisp = containerSC->StyleDisplay();
- }
- nscoord containerLH =
- ReflowInput::CalcLineHeight(nullptr, containerSC, NS_AUTOHEIGHT, 1.0f);
- RefPtr<nsFontMetrics> containerFM =
- nsLayoutUtils::GetFontMetricsForStyleContext(containerSC);
- MOZ_ASSERT(containerFM, "Should have fontMetrics!!");
- nscoord containerCH = containerFM->CapHeight();
- RefPtr<nsFontMetrics> firstLetterFM =
- nsLayoutUtils::GetFontMetricsForStyleContext(this);
- MOZ_ASSERT(firstLetterFM, "Should have fontMetrics!!");
- nscoord firstLetterCH = firstLetterFM->CapHeight();
- nsStyleFont* mutableStyleFont = GET_UNIQUE_STYLE_DATA(Font);
- float invCapHeightRatio =
- mutableStyleFont->mFont.size / NSCoordToFloat(firstLetterCH);
- mutableStyleFont->mFont.size =
- NSToCoordRound(((textReset->mInitialLetterSize - 1) * containerLH +
- containerCH) *
- invCapHeightRatio);
- }
- }
-
- // Change writing mode of text frame for text-combine-upright. We use
- // style structs of the parent to avoid triggering computation before
- // we change the writing mode.
- // It is safe to look at the parent's style because we are looking at
- // inherited properties, and ::-moz-text never matches any rules.
- if (mPseudoTag == nsCSSAnonBoxes::mozText && mParent &&
- mParent->StyleVisibility()->mWritingMode !=
- NS_STYLE_WRITING_MODE_HORIZONTAL_TB &&
- mParent->StyleText()->mTextCombineUpright ==
- NS_STYLE_TEXT_COMBINE_UPRIGHT_ALL) {
- MOZ_ASSERT(!PeekStyleVisibility(), "If StyleVisibility was already "
- "computed, some properties may have been computed "
- "incorrectly based on the old writing mode value");
- nsStyleVisibility* mutableVis = GET_UNIQUE_STYLE_DATA(Visibility);
- mutableVis->mWritingMode = NS_STYLE_WRITING_MODE_HORIZONTAL_TB;
- }
-
- // CSS 2.1 10.1: Propagate the root element's 'direction' to the ICB.
- // (PageContentFrame/CanvasFrame etc will inherit 'direction')
- if (mPseudoTag == nsCSSAnonBoxes::viewport) {
- nsPresContext* presContext = PresContext();
- mozilla::dom::Element* docElement = presContext->Document()->GetRootElement();
- if (docElement) {
- RefPtr<nsStyleContext> rootStyle =
- presContext->StyleSet()->AsGecko()->ResolveStyleFor(docElement, nullptr);
- auto dir = rootStyle->StyleVisibility()->mDirection;
- if (dir != StyleVisibility()->mDirection) {
- nsStyleVisibility* uniqueVisibility = GET_UNIQUE_STYLE_DATA(Visibility);
- uniqueVisibility->mDirection = dir;
- }
- }
- }
-
- // Correct tables.
- const nsStyleDisplay* disp = StyleDisplay();
- if (disp->mDisplay == mozilla::StyleDisplay::Table) {
- // -moz-center and -moz-right are used for HTML's alignment
- // This is covering the <div align="right"><table>...</table></div> case.
- // In this case, we don't want to inherit the text alignment into the table.
- const nsStyleText* text = StyleText();
-
- if (text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_LEFT ||
- text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
- text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)
- {
- nsStyleText* uniqueText = GET_UNIQUE_STYLE_DATA(Text);
- uniqueText->mTextAlign = NS_STYLE_TEXT_ALIGN_START;
- }
- }
-
- // CSS2.1 section 9.2.4 specifies fixups for the 'display' property of
- // the root element. We can't implement them in nsRuleNode because we
- // don't want to store all display structs that aren't 'block',
- // 'inline', or 'table' in the style context tree on the off chance
- // that the root element has its style reresolved later. So do them
- // here if needed, by changing the style data, so that other code
- // doesn't get confused by looking at the style data.
- if (!mParent &&
- // We don't want to blockify various anon boxes that just happen to not
- // inherit from anything. So restrict blockification only to actual
- // elements, the viewport (which should be block anyway, but in SVG
- // document's isn't because we lazy-load ua.css there), and the ::backdrop
- // pseudo-element. This last is explicitly allowed to have any specified
- // display type in the spec, but computes to a blockified display type per
- // various provisions of
- // https://fullscreen.spec.whatwg.org/#new-stacking-layer
- (!mPseudoTag ||
- mPseudoTag == nsCSSAnonBoxes::viewport ||
- mPseudoTag == nsCSSPseudoElements::backdrop)) {
- auto displayVal = disp->mDisplay;
- if (displayVal != mozilla::StyleDisplay::Contents) {
- nsRuleNode::EnsureBlockDisplay(displayVal, true);
- } else {
- // http://dev.w3.org/csswg/css-display/#transformations
- // "... a display-outside of 'contents' computes to block-level
- // on the root element."
- displayVal = mozilla::StyleDisplay::Block;
- }
- if (displayVal != disp->mDisplay) {
- nsStyleDisplay* mutable_display = GET_UNIQUE_STYLE_DATA(Display);
- disp = mutable_display;
-
- // If we're in this code, then mOriginalDisplay doesn't matter
- // for purposes of the cascade (because this nsStyleDisplay
- // isn't living in the ruletree anyway), and for determining
- // hypothetical boxes it's better to have mOriginalDisplay
- // matching mDisplay here.
- mutable_display->mOriginalDisplay = mutable_display->mDisplay =
- displayVal;
- }
- }
-
- // Adjust the "display" values of flex and grid items (but not for raw text
- // or placeholders). CSS3 Flexbox section 4 says:
- // # The computed 'display' of a flex item is determined
- // # by applying the table in CSS 2.1 Chapter 9.7.
- // ...which converts inline-level elements to their block-level equivalents.
- // Any block-level element directly contained by elements with ruby display
- // values are converted to their inline-level equivalents.
- if (!aSkipParentDisplayBasedStyleFixup && mParent) {
- // Skip display:contents ancestors to reach the potential container.
- // (If there are only display:contents ancestors between this node and
- // a flex/grid container ancestor, then this node is a flex/grid item, since
- // its parent *in the frame tree* will be the flex/grid container. So we treat
- // it like a flex/grid item here.)
- nsStyleContext* containerContext = mParent;
- const nsStyleDisplay* containerDisp = containerContext->StyleDisplay();
- while (containerDisp->mDisplay == mozilla::StyleDisplay::Contents) {
- if (!containerContext->GetParent()) {
- break;
- }
- containerContext = containerContext->GetParent();
- containerDisp = containerContext->StyleDisplay();
- }
- if (ShouldBlockifyChildren(containerDisp) &&
- !nsCSSAnonBoxes::IsNonElement(GetPseudo())) {
- // NOTE: Technically, we shouldn't modify the 'display' value of
- // positioned elements, since they aren't flex/grid items. However,
- // we don't need to worry about checking for that, because if we're
- // positioned, we'll have already been through a call to
- // EnsureBlockDisplay() in nsRuleNode, so this call here won't change
- // anything. So we're OK.
- auto displayVal = disp->mDisplay;
- nsRuleNode::EnsureBlockDisplay(displayVal);
- if (displayVal != disp->mDisplay) {
- NS_ASSERTION(!disp->IsAbsolutelyPositionedStyle(),
- "We shouldn't be changing the display value of "
- "positioned content (and we should have already "
- "converted its display value to be block-level...)");
- nsStyleDisplay* mutable_display = GET_UNIQUE_STYLE_DATA(Display);
- disp = mutable_display;
- mutable_display->mDisplay = displayVal;
- }
- }
- }
-
- // Note: This must come after the blockification above, otherwise we fail
- // the grid-item-blockifying-001.html reftest.
- if (mParent && ::ShouldSuppressLineBreak(this, disp, mParent,
- mParent->StyleDisplay())) {
- mBits |= NS_STYLE_SUPPRESS_LINEBREAK;
- auto displayVal = disp->mDisplay;
- nsRuleNode::EnsureInlineDisplay(displayVal);
- if (displayVal != disp->mDisplay) {
- nsStyleDisplay* mutable_display = GET_UNIQUE_STYLE_DATA(Display);
- disp = mutable_display;
- mutable_display->mDisplay = displayVal;
- }
- }
- // Suppress border/padding of ruby level containers
- if (disp->mDisplay == mozilla::StyleDisplay::RubyBaseContainer ||
- disp->mDisplay == mozilla::StyleDisplay::RubyTextContainer) {
- CreateEmptyStyleData(eStyleStruct_Border);
- CreateEmptyStyleData(eStyleStruct_Padding);
- }
- if (disp->IsRubyDisplayType()) {
- // Per CSS Ruby spec section Bidi Reordering, for all ruby boxes,
- // the 'normal' and 'embed' values of 'unicode-bidi' should compute to
- // 'isolate', and 'bidi-override' should compute to 'isolate-override'.
- const nsStyleTextReset* textReset = StyleTextReset();
- uint8_t unicodeBidi = textReset->mUnicodeBidi;
- if (unicodeBidi == NS_STYLE_UNICODE_BIDI_NORMAL ||
- unicodeBidi == NS_STYLE_UNICODE_BIDI_EMBED) {
- unicodeBidi = NS_STYLE_UNICODE_BIDI_ISOLATE;
- } else if (unicodeBidi == NS_STYLE_UNICODE_BIDI_BIDI_OVERRIDE) {
- unicodeBidi = NS_STYLE_UNICODE_BIDI_ISOLATE_OVERRIDE;
- }
- if (unicodeBidi != textReset->mUnicodeBidi) {
- nsStyleTextReset* mutableTextReset = GET_UNIQUE_STYLE_DATA(TextReset);
- mutableTextReset->mUnicodeBidi = unicodeBidi;
- }
- }
-
- /*
- * According to https://drafts.csswg.org/css-writing-modes-3/#block-flow:
- *
- * If a box has a different block flow direction than its containing block:
- * * If the box has a specified display of inline, its display computes
- * to inline-block. [CSS21]
- * ...etc.
- */
- if (disp->mDisplay == mozilla::StyleDisplay::Inline &&
- !nsCSSAnonBoxes::IsNonElement(mPseudoTag) &&
- mParent) {
- auto cbContext = mParent;
- while (cbContext->StyleDisplay()->mDisplay == mozilla::StyleDisplay::Contents) {
- cbContext = cbContext->mParent;
- }
- MOZ_ASSERT(cbContext, "the root context can't have display:contents");
- // We don't need the full mozilla::WritingMode value (incorporating dir
- // and text-orientation) here; just the writing-mode property is enough.
- if (StyleVisibility()->mWritingMode !=
- cbContext->StyleVisibility()->mWritingMode) {
- nsStyleDisplay* mutable_display = GET_UNIQUE_STYLE_DATA(Display);
- disp = mutable_display;
- mutable_display->mOriginalDisplay = mutable_display->mDisplay =
- mozilla::StyleDisplay::InlineBlock;
- }
- }
-
- // Compute User Interface style, to trigger loads of cursors
- StyleUserInterface();
-#undef GET_UNIQUE_STYLE_DATA
-}
-
template<class StyleContextLike>
nsChangeHint
nsStyleContext::CalcStyleDifferenceInternal(StyleContextLike* aNewContext,
uint32_t* aEqualStructs,
uint32_t* aSamePointerStructs)
{
PROFILER_LABEL("nsStyleContext", "CalcStyleDifference",
js::ProfileEntry::Category::CSS);
@@ -1448,41 +974,16 @@ nsStyleContext::SwapStyleData(nsStyleCon
thisData = nullptr;
}
} else if (!(aNewContext->mBits & bit) && thisData && otherData) {
std::swap(thisData, otherData);
}
}
}
-void
-nsStyleContext::SetIneligibleForSharing()
-{
- if (mBits & NS_STYLE_INELIGIBLE_FOR_SHARING) {
- return;
- }
- mBits |= NS_STYLE_INELIGIBLE_FOR_SHARING;
- if (const GeckoStyleContext* gecko = GetAsGecko()) {
- if (gecko->mChild) {
- GeckoStyleContext* child = gecko->mChild;
- do {
- child->SetIneligibleForSharing();
- child = child->mNextSibling;
- } while (gecko->mChild != child);
- }
- if (gecko->mEmptyChild) {
- GeckoStyleContext* child = gecko->mEmptyChild;
- do {
- child->SetIneligibleForSharing();
- child = child->mNextSibling;
- } while (gecko->mEmptyChild != child);
- }
- }
-}
-
#ifdef RESTYLE_LOGGING
nsCString
nsStyleContext::GetCachedStyleDataAsString(uint32_t aStructs)
{
nsCString structs;
for (nsStyleStructID i = nsStyleStructID(0);
i < nsStyleStructID_Length;
i = nsStyleStructID(i + 1)) {
@@ -1550,30 +1051,17 @@ nsStyleContext::LogStyleContextTree(bool
LOG_RESTYLE("%p(%d) %s%s%s%s",
this, mRefCnt,
structs.get(), pseudo.get(), flags.get(), parent.get());
LOG_RESTYLE_INDENT();
if (const GeckoStyleContext* gecko = GetAsGecko()) {
- if (nullptr != gecko->mChild) {
- GeckoStyleContext* child = gecko->mChild;
- do {
- child->LogStyleContextTree(false, aStructs);
- child = child->mNextSibling;
- } while (gecko->mChild != child);
- }
- if (nullptr != gecko->mEmptyChild) {
- GeckoStyleContext* child = gecko->mEmptyChild;
- do {
- child->LogStyleContextTree(false, aStructs);
- child = child->mNextSibling;
- } while (gecko->mEmptyChild != child);
- }
+ gecko->LogChildStyleContextTree(aStructs);
}
}
#endif
#ifdef DEBUG
/* static */ void
nsStyleContext::Initialize()
{
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -442,24 +442,16 @@ public:
* inheriting from the old ancestor. This is not normally a problem, as
* this style context will usually be destroyed by being released at the
* end of ElementRestyler::Restyle; but for style contexts held on to outside
* of the frame, we need to clear out the cached pointer so that if we need
* it again we'll re-fetch it from the new ancestor.
*/
void SwapStyleData(nsStyleContext* aNewContext, uint32_t aStructs);
-
- /**
- * Sets the NS_STYLE_INELIGIBLE_FOR_SHARING bit on this style context
- * and its descendants. If it finds a descendant that has the bit
- * already set, assumes that it can skip that subtree.
- */
- void SetIneligibleForSharing();
-
#ifdef DEBUG
void List(FILE* out, int32_t aIndent, bool aListDescendants = true);
static const char* StructName(nsStyleStructID aSID);
static bool LookupStruct(const nsACString& aName, nsStyleStructID& aResult);
#endif
#ifdef RESTYLE_LOGGING
nsCString GetCachedStyleDataAsString(uint32_t aStructs);
@@ -503,24 +495,18 @@ public: // temporary
// Helper post-contruct hook.
void FinishConstruction();
// Only does stuff in Gecko mode
void AddChild(nsStyleContext* aChild);
void RemoveChild(nsStyleContext* aChild);
- void* GetUniqueStyleData(const nsStyleStructID& aSID);
- void* CreateEmptyStyleData(const nsStyleStructID& aSID);
-
void SetStyleBits();
- // Only called for Gecko-backed nsStyleContexts.
- void ApplyStyleFixups(bool aSkipParentDisplayBasedStyleFixup);
-
const void* StyleStructFromServoComputedValues(nsStyleStructID aSID) {
switch (aSID) {
#define STYLE_STRUCT(name_, checkdata_cb_) \
case eStyleStruct_##name_: \
return Servo_GetStyle##name_(mSource.AsServoComputedValues());
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
default: