tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ContainStyleScopeManager.cpp (7656B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "ContainStyleScopeManager.h"
      8 
      9 #include "CounterStyleManager.h"
     10 #include "mozilla/ServoStyleSet.h"
     11 #include "nsContentUtils.h"
     12 #include "nsCounterManager.h"
     13 #include "nsIContent.h"
     14 #include "nsIContentInlines.h"
     15 #include "nsIFrame.h"
     16 #include "nsQuoteList.h"
     17 
     18 namespace mozilla {
     19 
     20 nsGenConNode* ContainStyleScope::GetPrecedingElementInGenConList(
     21    nsGenConList* aList) {
     22  nsContentUtils::NodeIndexCache cache;
     23  auto IsAfter = [this, &cache](nsGenConNode* aNode) {
     24    return nsContentUtils::CompareTreePosition<TreeKind::Flat>(
     25               mContent, aNode->mPseudoFrame->GetContent(),
     26               /* aCommonAncestor = */ nullptr, &cache) >= 0;
     27  };
     28  auto* last = aList->GetLast();
     29  if (!last || IsAfter(last)) {
     30    return last;
     31  }
     32  return aList->BinarySearch(IsAfter)->getPrevious();
     33 }
     34 
     35 void ContainStyleScope::RecalcAllCounters() {
     36  GetCounterManager().RecalcAll();
     37  for (auto* child : mChildren) {
     38    child->RecalcAllCounters();
     39  }
     40 }
     41 
     42 void ContainStyleScope::RecalcAllQuotes() {
     43  GetQuoteList().RecalcAll();
     44  for (auto* child : mChildren) {
     45    child->RecalcAllQuotes();
     46  }
     47 }
     48 
     49 ContainStyleScope& ContainStyleScopeManager::GetOrCreateScopeForContent(
     50    nsIContent* aContent) {
     51  for (; aContent; aContent = aContent->GetFlattenedTreeParent()) {
     52    auto* element = dom::Element::FromNode(*aContent);
     53    if (!element) {
     54      continue;
     55    }
     56 
     57    // Do not allow elements which have `display: contents` to create style
     58    // boundaries. See https://github.com/w3c/csswg-drafts/issues/7392.
     59    if (element->IsDisplayContents()) {
     60      continue;
     61    }
     62 
     63    const auto* style = Servo_Element_GetMaybeOutOfDateStyle(element);
     64    if (!style) {
     65      continue;
     66    }
     67 
     68    if (!style->SelfOrAncestorHasContainStyle()) {
     69      return GetRootScope();
     70    }
     71 
     72    if (!style->StyleDisplay()->IsContainStyle()) {
     73      continue;
     74    }
     75 
     76    if (auto* scope = mScopes.Get(aContent)) {
     77      return *scope;
     78    }
     79 
     80    auto& parentScope =
     81        GetOrCreateScopeForContent(aContent->GetFlattenedTreeParent());
     82    return *mScopes.InsertOrUpdate(
     83        aContent, MakeUnique<ContainStyleScope>(this, &parentScope, aContent));
     84  }
     85 
     86  return GetRootScope();
     87 }
     88 
     89 ContainStyleScope& ContainStyleScopeManager::GetScopeForContent(
     90    nsIContent* aContent) {
     91  MOZ_ASSERT(aContent);
     92 
     93  if (auto* element = dom::Element::FromNode(*aContent)) {
     94    if (const auto* style = Servo_Element_GetMaybeOutOfDateStyle(element)) {
     95      if (!style->SelfOrAncestorHasContainStyle()) {
     96        return GetRootScope();
     97      }
     98    }
     99  }
    100 
    101  for (; aContent; aContent = aContent->GetFlattenedTreeParent()) {
    102    if (auto* scope = mScopes.Get(aContent)) {
    103      return *scope;
    104    }
    105  }
    106 
    107  return GetRootScope();
    108 }
    109 
    110 void ContainStyleScopeManager::Clear() {
    111  GetRootScope().GetQuoteList().Clear();
    112  GetRootScope().GetCounterManager().Clear();
    113 
    114  DestroyScope(&GetRootScope());
    115  MOZ_DIAGNOSTIC_ASSERT(mScopes.IsEmpty(),
    116                        "Destroying the root scope should destroy all scopes.");
    117 }
    118 
    119 void ContainStyleScopeManager::DestroyScopesFor(nsIFrame* aFrame) {
    120  if (auto* scope = mScopes.Get(aFrame->GetContent())) {
    121    DestroyScope(scope);
    122  }
    123 }
    124 
    125 void ContainStyleScopeManager::DestroyScope(ContainStyleScope* aScope) {
    126  // Deleting a scope modifies the array of children in its parent, so we don't
    127  // use an iterator here.
    128  while (!aScope->GetChildren().IsEmpty()) {
    129    DestroyScope(aScope->GetChildren().ElementAt(0));
    130  }
    131  mScopes.Remove(aScope->GetContent());
    132 }
    133 
    134 bool ContainStyleScopeManager::DestroyCounterNodesFor(nsIFrame* aFrame) {
    135  bool result = false;
    136  for (auto* scope = &GetScopeForContent(aFrame->GetContent()); scope;
    137       scope = scope->GetParent()) {
    138    result |= scope->GetCounterManager().DestroyNodesFor(aFrame);
    139  }
    140  return result;
    141 }
    142 
    143 bool ContainStyleScopeManager::AddCounterChanges(nsIFrame* aNewFrame) {
    144  return GetOrCreateScopeForContent(
    145             aNewFrame->GetContent()->GetFlattenedTreeParent())
    146      .GetCounterManager()
    147      .AddCounterChanges(aNewFrame);
    148 }
    149 
    150 nsCounterList* ContainStyleScopeManager::GetOrCreateCounterList(
    151    dom::Element& aElement, nsAtom* aCounterName) {
    152  return GetOrCreateScopeForContent(&aElement)
    153      .GetCounterManager()
    154      .GetOrCreateCounterList(aCounterName);
    155 }
    156 
    157 bool ContainStyleScopeManager::CounterDirty(nsAtom* aCounterName) {
    158  return mDirtyCounters.Contains(aCounterName);
    159 }
    160 
    161 void ContainStyleScopeManager::SetCounterDirty(nsAtom* aCounterName) {
    162  mDirtyCounters.Insert(aCounterName);
    163 }
    164 
    165 void ContainStyleScopeManager::RecalcAllCounters() {
    166  GetRootScope().RecalcAllCounters();
    167  mDirtyCounters.Clear();
    168 }
    169 
    170 #if defined(DEBUG) || defined(MOZ_LAYOUT_DEBUGGER)
    171 void ContainStyleScopeManager::DumpCounters() {
    172  GetRootScope().GetCounterManager().Dump();
    173  for (auto& entry : mScopes) {
    174    entry.GetWeak()->GetCounterManager().Dump();
    175  }
    176 }
    177 #endif
    178 
    179 #ifdef ACCESSIBILITY
    180 static bool GetFirstCounterValueForScopeAndFrame(ContainStyleScope* aScope,
    181                                                 nsIFrame* aFrame,
    182                                                 CounterValue& aOrdinal) {
    183  if (aScope->GetCounterManager().GetFirstCounterValueForFrame(aFrame,
    184                                                               aOrdinal)) {
    185    return true;
    186  }
    187  for (auto* child : aScope->GetChildren()) {
    188    if (GetFirstCounterValueForScopeAndFrame(child, aFrame, aOrdinal)) {
    189      return true;
    190    }
    191  }
    192 
    193  return false;
    194 }
    195 
    196 void ContainStyleScopeManager::GetSpokenCounterText(nsIFrame* aFrame,
    197                                                    nsAString& aText) {
    198  using Tag = StyleCounterStyle::Tag;
    199  const auto& listStyleType = aFrame->StyleList()->mListStyleType;
    200  switch (listStyleType.tag) {
    201    case Tag::None:
    202      return;
    203    case Tag::String:
    204      listStyleType.AsString().AsAtom()->ToString(aText);
    205      return;
    206    case Tag::Symbols:
    207    case Tag::Name:
    208      break;
    209  }
    210 
    211  CounterValue ordinal = 1;
    212  GetFirstCounterValueForScopeAndFrame(&GetRootScope(), aFrame, ordinal);
    213 
    214  aFrame->PresContext()->CounterStyleManager()->WithCounterStyleNameOrSymbols(
    215      listStyleType, [&](CounterStyle* aStyle) {
    216        nsAutoString text;
    217        bool isBullet;
    218        aStyle->GetSpokenCounterText(ordinal, aFrame->GetWritingMode(), text,
    219                                     isBullet);
    220        if (isBullet) {
    221          aText = text;
    222          aText.Append(' ');
    223        } else {
    224          aStyle->GetPrefix(aText);
    225          aText += text;
    226          nsAutoString suffix;
    227          aStyle->GetSuffix(suffix);
    228          aText += suffix;
    229        }
    230      });
    231 }
    232 #endif
    233 
    234 void ContainStyleScopeManager::SetAllCountersDirty() {
    235  GetRootScope().GetCounterManager().SetAllDirty();
    236  for (auto& entry : mScopes) {
    237    entry.GetWeak()->GetCounterManager().SetAllDirty();
    238  }
    239 }
    240 
    241 bool ContainStyleScopeManager::DestroyQuoteNodesFor(nsIFrame* aFrame) {
    242  bool result = false;
    243  for (auto* scope = &GetScopeForContent(aFrame->GetContent()); scope;
    244       scope = scope->GetParent()) {
    245    result |= scope->GetQuoteList().DestroyNodesFor(aFrame);
    246  }
    247  return result;
    248 }
    249 
    250 nsQuoteList* ContainStyleScopeManager::QuoteListFor(dom::Element& aElement) {
    251  return &GetOrCreateScopeForContent(&aElement).GetQuoteList();
    252 }
    253 
    254 void ContainStyleScopeManager::RecalcAllQuotes() {
    255  GetRootScope().RecalcAllQuotes();
    256 }
    257 
    258 }  // namespace mozilla