tor-browser

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

nsQuoteList.cpp (5358B)


      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 /* implementation of quotes for the CSS 'content' property */
      8 
      9 #include "nsQuoteList.h"
     10 
     11 #include "mozilla/ContainStyleScopeManager.h"
     12 #include "mozilla/ErrorResult.h"
     13 #include "mozilla/dom/Text.h"
     14 #include "mozilla/intl/Quotes.h"
     15 #include "nsContainerFrame.h"
     16 #include "nsIContent.h"
     17 #include "nsIFrame.h"
     18 #include "nsIFrameInlines.h"
     19 #include "nsReadableUtils.h"
     20 
     21 using namespace mozilla;
     22 
     23 bool nsQuoteNode::InitTextFrame(nsGenConList* aList, nsIFrame* aPseudoFrame,
     24                                nsIFrame* aTextFrame) {
     25  nsGenConNode::InitTextFrame(aList, aPseudoFrame, aTextFrame);
     26 
     27  nsQuoteList* quoteList = static_cast<nsQuoteList*>(aList);
     28  bool dirty = false;
     29  quoteList->Insert(this);
     30  if (quoteList->IsLast(this)) {
     31    quoteList->Calc(this);
     32  } else {
     33    dirty = true;
     34  }
     35 
     36  // Don't set up text for 'no-open-quote' and 'no-close-quote'.
     37  if (IsRealQuote()) {
     38    aTextFrame->GetContent()->AsText()->SetText(Text(), false);
     39  }
     40  return dirty;
     41 }
     42 
     43 nsString nsQuoteNode::Text() {
     44  NS_ASSERTION(mType == StyleContentType::OpenQuote ||
     45                   mType == StyleContentType::CloseQuote,
     46               "should only be called when mText should be non-null");
     47  nsString result;
     48  int32_t depth = Depth();
     49  MOZ_ASSERT(depth >= -1);
     50 
     51  if (depth < 0) {
     52    return result;
     53  }
     54 
     55  const auto& quotesProp = mPseudoFrame->StyleList()->mQuotes;
     56 
     57  if (quotesProp.IsAuto()) {
     58    // Look up CLDR-derived quotation marks for the language of the context.
     59    const nsIFrame* frame = mPseudoFrame->GetInFlowParent();
     60    // Parent of the pseudo is the element around which the quotes are applied;
     61    // we want lang from *its* parent, unless it is the root.
     62    // XXX Are there other cases where we shouldn't look up to the parent?
     63    if (!frame->Style()->IsRootElementStyle()) {
     64      if (const nsIFrame* parent = frame->GetInFlowParent()) {
     65        frame = parent;
     66      }
     67    }
     68    const intl::Quotes* quotes =
     69        intl::QuotesForLang(frame->StyleFont()->mLanguage);
     70    // If we don't have quote-mark data for the language, use built-in
     71    // defaults.
     72    if (!quotes) {
     73      static const intl::Quotes sDefaultQuotes = {
     74          {0x201c, 0x201d, 0x2018, 0x2019}};
     75      quotes = &sDefaultQuotes;
     76    }
     77    size_t index = (depth == 0 ? 0 : 2);  // select first or second pair
     78    index += (mType == StyleContentType::OpenQuote ? 0 : 1);  // open or close
     79    result.Append(quotes->mChars[index]);
     80    return result;
     81  }
     82 
     83  MOZ_ASSERT(quotesProp.IsQuoteList());
     84  const Span<const StyleQuotePair> quotes = quotesProp.AsQuoteList().AsSpan();
     85 
     86  // Reuse the last pair when the depth is greater than the number of
     87  // pairs of quotes.  (Also make 'quotes: none' and close-quote from
     88  // a depth of 0 equivalent for the next test.)
     89  if (depth >= static_cast<int32_t>(quotes.Length())) {
     90    depth = static_cast<int32_t>(quotes.Length()) - 1;
     91  }
     92 
     93  if (depth == -1) {
     94    // close-quote from a depth of 0 or 'quotes: none'
     95    return result;
     96  }
     97 
     98  const StyleQuotePair& pair = quotes[depth];
     99  const StyleOwnedStr& quote =
    100      mType == StyleContentType::OpenQuote ? pair.opening : pair.closing;
    101  result.Assign(NS_ConvertUTF8toUTF16(quote.AsString()));
    102  return result;
    103 }
    104 
    105 static int32_t GetDepthBeforeFirstQuoteNode(ContainStyleScope* aScope) {
    106  for (auto* ancestor = aScope->GetParent(); ancestor;
    107       ancestor = ancestor->GetParent()) {
    108    auto& quoteList = ancestor->GetQuoteList();
    109    if (auto* node = static_cast<nsQuoteNode*>(
    110            aScope->GetPrecedingElementInGenConList(&quoteList))) {
    111      return node->DepthAfter();
    112    }
    113  }
    114  return 0;
    115 }
    116 
    117 void nsQuoteList::Calc(nsQuoteNode* aNode) {
    118  if (aNode == FirstNode()) {
    119    aNode->mDepthBefore = GetDepthBeforeFirstQuoteNode(mScope);
    120  } else {
    121    aNode->mDepthBefore = Prev(aNode)->DepthAfter();
    122  }
    123 }
    124 
    125 void nsQuoteList::RecalcAll() {
    126  for (nsQuoteNode* node = FirstNode(); node; node = Next(node)) {
    127    int32_t oldDepth = node->mDepthBefore;
    128    Calc(node);
    129 
    130    if (node->mDepthBefore != oldDepth && node->mText && node->IsRealQuote()) {
    131      node->mText->SetData(node->Text(), IgnoreErrors());
    132    }
    133  }
    134 }
    135 
    136 #ifdef DEBUG
    137 void nsQuoteList::PrintChain() {
    138  using StyleContentType = nsQuoteNode::StyleContentType;
    139 
    140  printf("Chain: \n");
    141  for (nsQuoteNode* node = FirstNode(); node; node = Next(node)) {
    142    printf("  %p %d - ", static_cast<void*>(node), node->mDepthBefore);
    143    switch (node->mType) {
    144      case StyleContentType::OpenQuote:
    145        printf("open");
    146        break;
    147      case StyleContentType::NoOpenQuote:
    148        printf("noOpen");
    149        break;
    150      case StyleContentType::CloseQuote:
    151        printf("close");
    152        break;
    153      case StyleContentType::NoCloseQuote:
    154        printf("noClose");
    155        break;
    156      default:
    157        printf("unknown!!!");
    158    }
    159    printf(" %d - %d,", node->Depth(), node->DepthAfter());
    160    if (node->mText) {
    161      nsAutoString data;
    162      node->mText->GetData(data);
    163      printf(" \"%s\",", NS_ConvertUTF16toUTF8(data).get());
    164    }
    165    printf("\n");
    166  }
    167 }
    168 #endif