/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/layout/TextAutosizer.h"

#include "core/dom/Document.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLTextAreaElement.h"
#include "core/layout/LayoutBlock.h"
#include "core/layout/LayoutInline.h"
#include "core/layout/LayoutListItem.h"
#include "core/layout/LayoutListMarker.h"
#include "core/layout/LayoutTable.h"
#include "core/layout/LayoutTableCell.h"
#include "core/layout/LayoutView.h"
#include "core/layout/api/LayoutAPIShim.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/page/Page.h"
#include "wtf/PtrUtil.h"
#include <memory>

#ifdef AUTOSIZING_DOM_DEBUG_INFO
#include "core/dom/ExecutionContextTask.h"
#endif

namespace blink {

#ifdef AUTOSIZING_DOM_DEBUG_INFO
class WriteDebugInfoTask : public ExecutionContextTask {
 public:
  WriteDebugInfoTask(Element* element, AtomicString value)
      : m_element(element), m_value(value) {}

  virtual void performTask(ExecutionContext*) {
    m_element->setAttribute("data-autosizing", m_value, ASSERT_NO_EXCEPTION);
  }

 private:
  Persistent<Element> m_element;
  AtomicString m_value;
};

static void writeDebugInfo(LayoutObject* layoutObject,
                           const AtomicString& output) {
  Node* node = layoutObject->node();
  if (!node)
    return;
  if (node->isDocumentNode())
    node = toDocument(node)->documentElement();
  if (!node->isElementNode())
    return;
  node->document().postTask(BLINK_FROM_HERE, wrapUnique(new WriteDebugInfoTask(
                                                 toElement(node), output)));
}

void TextAutosizer::writeClusterDebugInfo(Cluster* cluster) {
  String explanation = "";
  if (cluster->m_flags & SUPPRESSING) {
    explanation = "[suppressed]";
  } else if (!(cluster->m_flags & (INDEPENDENT | WIDER_OR_NARROWER))) {
    explanation = "[inherited]";
  } else if (cluster->m_supercluster) {
    explanation = "[supercluster]";
  } else if (!clusterHasEnoughTextToAutosize(cluster)) {
    explanation = "[insufficient-text]";
  } else {
    const LayoutBlock* widthProvider = clusterWidthProvider(cluster->m_root);
    if (cluster->m_hasTableAncestor &&
        cluster->m_multiplier < multiplierFromBlock(widthProvider)) {
      explanation = "[table-ancestor-limited]";
    } else {
      explanation =
          String::format("[from width %d of %s]",
                         static_cast<int>(widthFromBlock(widthProvider)),
                         widthProvider->debugName().utf8().data());
    }
  }
  String pageInfo = "";
  if (cluster->m_root->isLayoutView()) {
    pageInfo =
        String::format("; pageinfo: afsf %f * dsa %f * (lw %d / fw %d)",
                       m_pageInfo.m_accessibilityFontScaleFactor,
                       m_pageInfo.m_deviceScaleAdjustment,
                       m_pageInfo.m_layoutWidth, m_pageInfo.m_frameWidth);
  }
  float multiplier =
      cluster->m_flags & SUPPRESSING ? 1.0 : cluster->m_multiplier;
  writeDebugInfo(const_cast<LayoutBlock*>(cluster->m_root),
                 AtomicString(String::format("cluster: %f %s%s", multiplier,
                                             explanation.utf8().data(),
                                             pageInfo.utf8().data())));
}
#endif

static const LayoutObject* parentElementLayoutObject(
    const LayoutObject* layoutObject) {
  // At style recalc, the layoutObject's parent may not be attached,
  // so we need to obtain this from the DOM tree.
  const Node* node = layoutObject->node();
  if (!node)
    return nullptr;

  // FIXME: This should be using LayoutTreeBuilderTraversal::parent().
  if (Element* parent = node->parentElement())
    return parent->layoutObject();
  return nullptr;
}

static bool isNonTextAreaFormControl(const LayoutObject* layoutObject) {
  const Node* node = layoutObject ? layoutObject->node() : nullptr;
  if (!node || !node->isElementNode())
    return false;
  const Element* element = toElement(node);

  return (element->isFormControlElement() && !isHTMLTextAreaElement(element));
}

static bool isPotentialClusterRoot(const LayoutObject* layoutObject) {
  // "Potential cluster roots" are the smallest unit for which we can
  // enable/disable text autosizing.
  // - Must have children.
  //   An exception is made for LayoutView which should create a root to
  //   maintain consistency with documents that have no child nodes but may
  //   still have LayoutObject children.
  // - Must not be inline, as different multipliers on one line looks terrible.
  //   Exceptions are inline-block and alike elements (inline-table, -webkit-inline-*),
  //   as they often contain entire multi-line columns of text.
  // - Must not be normal list items, as items in the same list should look
  //   consistent, unless they are floating or position:absolute/fixed.
  Node* node = layoutObject->generatingNode();
  if (node && !node->hasChildren() && !layoutObject->isLayoutView())
    return false;
  if (!layoutObject->isLayoutBlock())
    return false;
  if (layoutObject->isInline() &&
      !layoutObject->style()->isDisplayReplacedType())
    return false;
  if (layoutObject->isListItem())
    return (layoutObject->isFloating() ||
            layoutObject->isOutOfFlowPositioned());

  return true;
}

static bool isIndependentDescendant(const LayoutBlock* layoutObject) {
  ASSERT(isPotentialClusterRoot(layoutObject));

  LayoutBlock* containingBlock = layoutObject->containingBlock();
  return layoutObject->isLayoutView() || layoutObject->isFloating() ||
         layoutObject->isOutOfFlowPositioned() || layoutObject->isTableCell() ||
         layoutObject->isTableCaption() ||
         layoutObject->isFlexibleBoxIncludingDeprecated() ||
         (containingBlock &&
          containingBlock->isHorizontalWritingMode() !=
              layoutObject->isHorizontalWritingMode()) ||
         layoutObject->style()->isDisplayReplacedType() ||
         layoutObject->isTextArea() ||
         layoutObject->style()->userModify() != READ_ONLY;
}

static bool blockIsRowOfLinks(const LayoutBlock* block) {
  // A "row of links" is a block for which:
  //  1. It does not contain non-link text elements longer than 3 characters
  //  2. It contains a minimum of 3 inline links and all links should
  //     have the same specified font size.
  //  3. It should not contain <br> elements.
  //  4. It should contain only inline elements unless they are containers,
  //     children of link elements or children of sub-containers.
  int linkCount = 0;
  LayoutObject* layoutObject = block->firstChild();
  float matchingFontSize = -1;

  while (layoutObject) {
    if (!isPotentialClusterRoot(layoutObject)) {
      if (layoutObject->isText() &&
          toLayoutText(layoutObject)->text().stripWhiteSpace().length() > 3)
        return false;
      if (!layoutObject->isInline() || layoutObject->isBR())
        return false;
    }
    if (layoutObject->style()->isLink()) {
      linkCount++;
      if (matchingFontSize < 0)
        matchingFontSize = layoutObject->style()->specifiedFontSize();
      else if (matchingFontSize != layoutObject->style()->specifiedFontSize())
        return false;

      // Skip traversing descendants of the link.
      layoutObject = layoutObject->nextInPreOrderAfterChildren(block);
      continue;
    }
    layoutObject = layoutObject->nextInPreOrder(block);
  }

  return (linkCount >= 3);
}

static bool blockHeightConstrained(const LayoutBlock* block) {
  // FIXME: Propagate constrainedness down the tree, to avoid inefficiently walking back up from each box.
  // FIXME: This code needs to take into account vertical writing modes.
  // FIXME: Consider additional heuristics, such as ignoring fixed heights if the content is already overflowing before autosizing kicks in.
  for (; block; block = block->containingBlock()) {
    const ComputedStyle& style = block->styleRef();
    if (style.overflowY() >= OverflowScroll)
      return false;
    if (style.height().isSpecified() || style.maxHeight().isSpecified() ||
        block->isOutOfFlowPositioned()) {
      // Some sites (e.g. wikipedia) set their html and/or body elements to height:100%,
      // without intending to constrain the height of the content within them.
      return !block->isDocumentElement() && !block->isBody() &&
             !block->isLayoutView();
    }
    if (block->isFloating())
      return false;
  }
  return false;
}

static bool blockOrImmediateChildrenAreFormControls(const LayoutBlock* block) {
  if (isNonTextAreaFormControl(block))
    return true;
  const LayoutObject* layoutObject = block->firstChild();
  while (layoutObject) {
    if (isNonTextAreaFormControl(layoutObject))
      return true;
    layoutObject = layoutObject->nextSibling();
  }

  return false;
}

// Some blocks are not autosized even if their parent cluster wants them to.
static bool blockSuppressesAutosizing(const LayoutBlock* block) {
  if (blockOrImmediateChildrenAreFormControls(block))
    return true;

  if (blockIsRowOfLinks(block))
    return true;

  // Don't autosize block-level text that can't wrap (as it's likely to
  // expand sideways and break the page's layout).
  if (!block->style()->autoWrap())
    return true;

  if (blockHeightConstrained(block))
    return true;

  return false;
}

static bool hasExplicitWidth(const LayoutBlock* block) {
  // FIXME: This heuristic may need to be expanded to other ways a block can be wider or narrower
  //        than its parent containing block.
  return block->style() && block->style()->width().isSpecified();
}

TextAutosizer::TextAutosizer(const Document* document)
    : m_document(document),
      m_firstBlockToBeginLayout(nullptr),
#if ENABLE(ASSERT)
      m_blocksThatHaveBegunLayout(),
#endif
      m_superclusters(),
      m_clusterStack(),
      m_fingerprintMapper(),
      m_pageInfo(),
      m_updatePageInfoDeferred(false) {
}

TextAutosizer::~TextAutosizer() {}

void TextAutosizer::record(const LayoutBlock* block) {
  if (!m_pageInfo.m_settingEnabled)
    return;

  ASSERT(!m_blocksThatHaveBegunLayout.contains(block));

  if (!classifyBlock(block, INDEPENDENT | EXPLICIT_WIDTH))
    return;

  if (Fingerprint fingerprint = computeFingerprint(block))
    m_fingerprintMapper.addTentativeClusterRoot(block, fingerprint);
}

void TextAutosizer::destroy(const LayoutBlock* block) {
  if (!m_pageInfo.m_settingEnabled && !m_fingerprintMapper.hasFingerprints())
    return;

  ASSERT(!m_blocksThatHaveBegunLayout.contains(block));

  if (m_fingerprintMapper.remove(block) && m_firstBlockToBeginLayout) {
    // LayoutBlock with a fingerprint was destroyed during layout.
    // Clear the cluster stack and the supercluster map to avoid stale pointers.
    // Speculative fix for http://crbug.com/369485.
    m_firstBlockToBeginLayout = nullptr;
    m_clusterStack.clear();
    m_superclusters.clear();
  }
}

TextAutosizer::BeginLayoutBehavior TextAutosizer::prepareForLayout(
    const LayoutBlock* block) {
#if ENABLE(ASSERT)
  m_blocksThatHaveBegunLayout.add(block);
#endif

  if (!m_firstBlockToBeginLayout) {
    m_firstBlockToBeginLayout = block;
    prepareClusterStack(block->parent());
  } else if (block == currentCluster()->m_root) {
    // Ignore beginLayout on the same block twice.
    // This can happen with paginated overflow.
    return StopLayout;
  }

  return ContinueLayout;
}

void TextAutosizer::prepareClusterStack(const LayoutObject* layoutObject) {
  if (!layoutObject)
    return;
  prepareClusterStack(layoutObject->parent());

  if (layoutObject->isLayoutBlock()) {
    const LayoutBlock* block = toLayoutBlock(layoutObject);
#if ENABLE(ASSERT)
    m_blocksThatHaveBegunLayout.add(block);
#endif
    if (Cluster* cluster = maybeCreateCluster(block))
      m_clusterStack.append(wrapUnique(cluster));
  }
}

void TextAutosizer::beginLayout(LayoutBlock* block,
                                SubtreeLayoutScope* layouter) {
  ASSERT(shouldHandleLayout());

  if (prepareForLayout(block) == StopLayout)
    return;

  ASSERT(!m_clusterStack.isEmpty() || block->isLayoutView());

  if (Cluster* cluster = maybeCreateCluster(block))
    m_clusterStack.append(wrapUnique(cluster));

  ASSERT(!m_clusterStack.isEmpty());

  // Cells in auto-layout tables are handled separately by inflateAutoTable.
  bool isAutoTableCell =
      block->isTableCell() &&
      !toLayoutTableCell(block)->table()->style()->isFixedTableLayout();
  if (!isAutoTableCell && !m_clusterStack.isEmpty())
    inflate(block, layouter);
}

void TextAutosizer::inflateAutoTable(LayoutTable* table) {
  ASSERT(table);
  ASSERT(!table->style()->isFixedTableLayout());
  ASSERT(table->containingBlock());

  Cluster* cluster = currentCluster();
  if (cluster->m_root != table)
    return;

  // Pre-inflate cells that have enough text so that their inflated preferred widths will be used
  // for column sizing.
  for (LayoutObject* section = table->firstChild(); section;
       section = section->nextSibling()) {
    if (!section->isTableSection())
      continue;
    for (LayoutTableRow* row = toLayoutTableSection(section)->firstRow(); row;
         row = row->nextRow()) {
      for (LayoutTableCell* cell = row->firstCell(); cell;
           cell = cell->nextCell()) {
        if (!cell->needsLayout())
          continue;

        beginLayout(cell, nullptr);
        inflate(cell, nullptr, DescendToInnerBlocks);
        endLayout(cell);
      }
    }
  }
}

void TextAutosizer::endLayout(LayoutBlock* block) {
  ASSERT(shouldHandleLayout());

  if (block == m_firstBlockToBeginLayout) {
    m_firstBlockToBeginLayout = nullptr;
    m_clusterStack.clear();
    m_superclusters.clear();
    m_stylesRetainedDuringLayout.clear();
#if ENABLE(ASSERT)
    m_blocksThatHaveBegunLayout.clear();
#endif
    // Tables can create two layout scopes for the same block so the isEmpty
    // check below is needed to guard against endLayout being called twice.
  } else if (!m_clusterStack.isEmpty() && currentCluster()->m_root == block) {
    m_clusterStack.removeLast();
  }
}

float TextAutosizer::inflate(LayoutObject* parent,
                             SubtreeLayoutScope* layouter,
                             InflateBehavior behavior,
                             float multiplier) {
  Cluster* cluster = currentCluster();
  bool hasTextChild = false;

  LayoutObject* child = nullptr;
  if (parent->isLayoutBlock() &&
      (parent->childrenInline() || behavior == DescendToInnerBlocks))
    child = toLayoutBlock(parent)->firstChild();
  else if (parent->isLayoutInline())
    child = toLayoutInline(parent)->firstChild();

  while (child) {
    if (child->isText()) {
      hasTextChild = true;
      // We only calculate this multiplier on-demand to ensure the parent block of this text
      // has entered layout.
      if (!multiplier)
        multiplier =
            cluster->m_flags & SUPPRESSING ? 1.0f : clusterMultiplier(cluster);
      applyMultiplier(child, multiplier, layouter);

      // FIXME: Investigate why MarkOnlyThis is sufficient.
      if (parent->isLayoutInline())
        child->setPreferredLogicalWidthsDirty(MarkOnlyThis);
    } else if (child->isLayoutInline()) {
      multiplier = inflate(child, layouter, behavior, multiplier);
    } else if (child->isLayoutBlock() && behavior == DescendToInnerBlocks &&
               !classifyBlock(child,
                              INDEPENDENT | EXPLICIT_WIDTH | SUPPRESSING)) {
      multiplier = inflate(child, layouter, behavior, multiplier);
    }
    child = child->nextSibling();
  }

  if (hasTextChild) {
    applyMultiplier(parent, multiplier,
                    layouter);  // Parent handles line spacing.
  } else if (!parent->isListItem()) {
    // For consistency, a block with no immediate text child should always have a
    // multiplier of 1.
    applyMultiplier(parent, 1, layouter);
  }

  if (parent->isListItem()) {
    float multiplier = clusterMultiplier(cluster);
    applyMultiplier(parent, multiplier, layouter);

    // The list item has to be treated special because we can have a tree such that you have
    // a list item for a form inside it. The list marker then ends up inside the form and when
    // we try to get the clusterMultiplier we have the wrong cluster root to work from and get
    // the wrong value.
    LayoutListItem* item = toLayoutListItem(parent);
    if (LayoutListMarker* marker = item->marker()) {
      applyMultiplier(marker, multiplier, layouter);
      marker->setPreferredLogicalWidthsDirty(MarkOnlyThis);
    }
  }

  if (m_pageInfo.m_hasAutosized)
    UseCounter::count(*m_document, UseCounter::TextAutosizing);

  return multiplier;
}

bool TextAutosizer::shouldHandleLayout() const {
  return m_pageInfo.m_settingEnabled && m_pageInfo.m_pageNeedsAutosizing &&
         !m_updatePageInfoDeferred;
}

bool TextAutosizer::pageNeedsAutosizing() const {
  return m_pageInfo.m_pageNeedsAutosizing;
}

void TextAutosizer::updatePageInfoInAllFrames() {
  ASSERT(!m_document->frame() || m_document->frame()->isMainFrame());

  for (Frame* frame = m_document->frame(); frame;
       frame = frame->tree().traverseNext()) {
    if (!frame->isLocalFrame())
      continue;

    Document* document = toLocalFrame(frame)->document();
    // If document is being detached, skip updatePageInfo.
    if (!document || !document->isActive())
      continue;
    if (TextAutosizer* textAutosizer = document->textAutosizer())
      textAutosizer->updatePageInfo();
  }
}

void TextAutosizer::updatePageInfo() {
  if (m_updatePageInfoDeferred || !m_document->page() ||
      !m_document->settings())
    return;

  PageInfo previousPageInfo(m_pageInfo);
  m_pageInfo.m_settingEnabled = m_document->settings()->textAutosizingEnabled();

  if (!m_pageInfo.m_settingEnabled || m_document->printing()) {
    m_pageInfo.m_pageNeedsAutosizing = false;
  } else {
    LayoutViewItem layoutViewItem = m_document->layoutViewItem();
    bool horizontalWritingMode =
        isHorizontalWritingMode(layoutViewItem.style()->getWritingMode());

    // FIXME: With out-of-process iframes, the top frame can be remote and
    // doesn't have sizing information. Just return if this is the case.
    Frame* frame = m_document->frame()->tree().top();
    if (frame->isRemoteFrame())
      return;

    LocalFrame* mainFrame = toLocalFrame(frame);
    IntSize frameSize =
        m_document->settings()->textAutosizingWindowSizeOverride();
    if (frameSize.isEmpty())
      frameSize = windowSize();

    m_pageInfo.m_frameWidth =
        horizontalWritingMode ? frameSize.width() : frameSize.height();

    IntSize layoutSize = mainFrame->view()->layoutSize();
    m_pageInfo.m_layoutWidth =
        horizontalWritingMode ? layoutSize.width() : layoutSize.height();

    // TODO(pdr): Accessibility should be moved out of the text autosizer. See: crbug.com/645717.
    m_pageInfo.m_accessibilityFontScaleFactor =
        m_document->settings()->accessibilityFontScaleFactor();

    // If the page has a meta viewport or @viewport, don't apply the device scale adjustment.
    if (!mainFrame->document()->viewportDescription().isSpecifiedByAuthor())
      m_pageInfo.m_deviceScaleAdjustment =
          m_document->settings()->deviceScaleAdjustment();
    else
      m_pageInfo.m_deviceScaleAdjustment = 1.0f;

    // TODO(pdr): pageNeedsAutosizing should take into account whether text-size-adjust is used
    // anywhere on the page because that also needs to trigger autosizing. See: crbug.com/646237.
    m_pageInfo.m_pageNeedsAutosizing =
        !!m_pageInfo.m_frameWidth &&
        (m_pageInfo.m_accessibilityFontScaleFactor *
             m_pageInfo.m_deviceScaleAdjustment *
             (static_cast<float>(m_pageInfo.m_layoutWidth) /
              m_pageInfo.m_frameWidth) >
         1.0f);
  }

  if (m_pageInfo.m_pageNeedsAutosizing) {
    // If page info has changed, multipliers may have changed. Force a layout to recompute them.
    if (m_pageInfo.m_frameWidth != previousPageInfo.m_frameWidth ||
        m_pageInfo.m_layoutWidth != previousPageInfo.m_layoutWidth ||
        m_pageInfo.m_accessibilityFontScaleFactor !=
            previousPageInfo.m_accessibilityFontScaleFactor ||
        m_pageInfo.m_deviceScaleAdjustment !=
            previousPageInfo.m_deviceScaleAdjustment ||
        m_pageInfo.m_settingEnabled != previousPageInfo.m_settingEnabled)
      setAllTextNeedsLayout();
  } else if (previousPageInfo.m_hasAutosized) {
    // If we are no longer autosizing the page, we won't do anything during the next layout.
    // Set all the multipliers back to 1 now.
    resetMultipliers();
    m_pageInfo.m_hasAutosized = false;
  }
}

IntSize TextAutosizer::windowSize() const {
  Page* page = m_document->page();
  ASSERT(page);
  return page->frameHost().visualViewport().size();
}

void TextAutosizer::resetMultipliers() {
  LayoutObject* layoutObject =
      LayoutAPIShim::layoutObjectFrom(m_document->layoutViewItem());
  while (layoutObject) {
    if (const ComputedStyle* style = layoutObject->style()) {
      if (style->textAutosizingMultiplier() != 1)
        applyMultiplier(layoutObject, 1, nullptr, LayoutNeeded);
    }
    layoutObject = layoutObject->nextInPreOrder();
  }
}

void TextAutosizer::setAllTextNeedsLayout() {
  LayoutItem layoutItem = m_document->layoutViewItem();
  while (!layoutItem.isNull()) {
    if (layoutItem.isText())
      layoutItem.setNeedsLayoutAndFullPaintInvalidation(
          LayoutInvalidationReason::TextAutosizing);
    layoutItem = layoutItem.nextInPreOrder();
  }
}

TextAutosizer::BlockFlags TextAutosizer::classifyBlock(
    const LayoutObject* layoutObject,
    BlockFlags mask) const {
  if (!layoutObject->isLayoutBlock())
    return 0;

  const LayoutBlock* block = toLayoutBlock(layoutObject);
  BlockFlags flags = 0;

  if (isPotentialClusterRoot(block)) {
    if (mask & POTENTIAL_ROOT)
      flags |= POTENTIAL_ROOT;

    if ((mask & INDEPENDENT) &&
        (isIndependentDescendant(block) || block->isTable()))
      flags |= INDEPENDENT;

    if ((mask & EXPLICIT_WIDTH) && hasExplicitWidth(block))
      flags |= EXPLICIT_WIDTH;

    if ((mask & SUPPRESSING) && blockSuppressesAutosizing(block))
      flags |= SUPPRESSING;
  }
  return flags;
}

bool TextAutosizer::clusterWouldHaveEnoughTextToAutosize(
    const LayoutBlock* root,
    const LayoutBlock* widthProvider) {
  Cluster hypotheticalCluster(root, classifyBlock(root), nullptr);
  return clusterHasEnoughTextToAutosize(&hypotheticalCluster, widthProvider);
}

bool TextAutosizer::clusterHasEnoughTextToAutosize(
    Cluster* cluster,
    const LayoutBlock* widthProvider) {
  if (cluster->m_hasEnoughTextToAutosize != UnknownAmountOfText)
    return cluster->m_hasEnoughTextToAutosize == HasEnoughText;

  const LayoutBlock* root = cluster->m_root;
  if (!widthProvider)
    widthProvider = clusterWidthProvider(root);

  // TextAreas and user-modifiable areas get a free pass to autosize regardless of text content.
  if (root->isTextArea() ||
      (root->style() && root->style()->userModify() != READ_ONLY)) {
    cluster->m_hasEnoughTextToAutosize = HasEnoughText;
    return true;
  }

  if (cluster->m_flags & SUPPRESSING) {
    cluster->m_hasEnoughTextToAutosize = NotEnoughText;
    return false;
  }

  // 4 lines of text is considered enough to autosize.
  float minimumTextLengthToAutosize = widthFromBlock(widthProvider) * 4;

  float length = 0;
  LayoutObject* descendant = root->firstChild();
  while (descendant) {
    if (descendant->isLayoutBlock()) {
      if (classifyBlock(descendant, INDEPENDENT | SUPPRESSING)) {
        descendant = descendant->nextInPreOrderAfterChildren(root);
        continue;
      }
    } else if (descendant->isText()) {
      // Note: Using text().stripWhiteSpace().length() instead of resolvedTextLength() because
      // the lineboxes will not be built until layout. These values can be different.
      // Note: This is an approximation assuming each character is 1em wide.
      length += toLayoutText(descendant)->text().stripWhiteSpace().length() *
                descendant->style()->specifiedFontSize();

      if (length >= minimumTextLengthToAutosize) {
        cluster->m_hasEnoughTextToAutosize = HasEnoughText;
        return true;
      }
    }
    descendant = descendant->nextInPreOrder(root);
  }

  cluster->m_hasEnoughTextToAutosize = NotEnoughText;
  return false;
}

TextAutosizer::Fingerprint TextAutosizer::getFingerprint(
    const LayoutObject* layoutObject) {
  Fingerprint result = m_fingerprintMapper.get(layoutObject);
  if (!result) {
    result = computeFingerprint(layoutObject);
    m_fingerprintMapper.add(layoutObject, result);
  }
  return result;
}

TextAutosizer::Fingerprint TextAutosizer::computeFingerprint(
    const LayoutObject* layoutObject) {
  Node* node = layoutObject->generatingNode();
  if (!node || !node->isElementNode())
    return 0;

  FingerprintSourceData data;
  if (const LayoutObject* parent = parentElementLayoutObject(layoutObject))
    data.m_parentHash = getFingerprint(parent);

  data.m_qualifiedNameHash =
      QualifiedNameHash::hash(toElement(node)->tagQName());

  if (const ComputedStyle* style = layoutObject->style()) {
    data.m_packedStyleProperties = style->direction();
    data.m_packedStyleProperties |= (style->position() << 1);
    data.m_packedStyleProperties |=
        (static_cast<unsigned>(style->floating()) << 4);
    data.m_packedStyleProperties |=
        (static_cast<unsigned>(style->display()) << 6);
    data.m_packedStyleProperties |= (style->width().type() << 11);
    // packedStyleProperties effectively using 15 bits now.

    // consider for adding: writing mode, padding.

    data.m_width = style->width().getFloatValue();
  }

  // Use nodeIndex as a rough approximation of column number
  // (it's too early to call LayoutTableCell::col).
  // FIXME: account for colspan
  if (layoutObject->isTableCell())
    data.m_column = layoutObject->node()->nodeIndex();

  return StringHasher::computeHash<UChar>(
      static_cast<const UChar*>(static_cast<const void*>(&data)),
      sizeof data / sizeof(UChar));
}

TextAutosizer::Cluster* TextAutosizer::maybeCreateCluster(
    const LayoutBlock* block) {
  BlockFlags flags = classifyBlock(block);
  if (!(flags & POTENTIAL_ROOT))
    return nullptr;

  Cluster* parentCluster =
      m_clusterStack.isEmpty() ? nullptr : currentCluster();
  ASSERT(parentCluster || block->isLayoutView());

  // If a non-independent block would not alter the SUPPRESSING flag, it doesn't need to be a cluster.
  bool parentSuppresses =
      parentCluster && (parentCluster->m_flags & SUPPRESSING);
  if (!(flags & INDEPENDENT) && !(flags & EXPLICIT_WIDTH) &&
      !!(flags & SUPPRESSING) == parentSuppresses)
    return nullptr;

  Cluster* cluster =
      new Cluster(block, flags, parentCluster, getSupercluster(block));
#ifdef AUTOSIZING_DOM_DEBUG_INFO
  // Non-SUPPRESSING clusters are annotated in clusterMultiplier.
  if (flags & SUPPRESSING)
    writeClusterDebugInfo(cluster);
#endif
  return cluster;
}

TextAutosizer::Supercluster* TextAutosizer::getSupercluster(
    const LayoutBlock* block) {
  Fingerprint fingerprint = m_fingerprintMapper.get(block);
  if (!fingerprint)
    return nullptr;

  BlockSet* roots = m_fingerprintMapper.getTentativeClusterRoots(fingerprint);
  if (!roots || roots->size() < 2 || !roots->contains(block))
    return nullptr;

  SuperclusterMap::AddResult addResult =
      m_superclusters.add(fingerprint, std::unique_ptr<Supercluster>());
  if (!addResult.isNewEntry)
    return addResult.storedValue->value.get();

  Supercluster* supercluster = new Supercluster(roots);
  addResult.storedValue->value = wrapUnique(supercluster);
  return supercluster;
}

float TextAutosizer::clusterMultiplier(Cluster* cluster) {
  if (cluster->m_multiplier)
    return cluster->m_multiplier;

  // FIXME: why does isWiderOrNarrowerDescendant crash on independent clusters?
  if (!(cluster->m_flags & INDEPENDENT) && isWiderOrNarrowerDescendant(cluster))
    cluster->m_flags |= WIDER_OR_NARROWER;

  if (cluster->m_flags & (INDEPENDENT | WIDER_OR_NARROWER)) {
    if (cluster->m_supercluster)
      cluster->m_multiplier = superclusterMultiplier(cluster);
    else if (clusterHasEnoughTextToAutosize(cluster))
      cluster->m_multiplier =
          multiplierFromBlock(clusterWidthProvider(cluster->m_root));
    else
      cluster->m_multiplier = 1.0f;
  } else {
    cluster->m_multiplier =
        cluster->m_parent ? clusterMultiplier(cluster->m_parent) : 1.0f;
  }

#ifdef AUTOSIZING_DOM_DEBUG_INFO
  writeClusterDebugInfo(cluster);
#endif

  ASSERT(cluster->m_multiplier);
  return cluster->m_multiplier;
}

bool TextAutosizer::superclusterHasEnoughTextToAutosize(
    Supercluster* supercluster,
    const LayoutBlock* widthProvider) {
  if (supercluster->m_hasEnoughTextToAutosize != UnknownAmountOfText)
    return supercluster->m_hasEnoughTextToAutosize == HasEnoughText;

  for (auto* root : *supercluster->m_roots) {
    if (clusterWouldHaveEnoughTextToAutosize(root, widthProvider)) {
      supercluster->m_hasEnoughTextToAutosize = HasEnoughText;
      return true;
    }
  }
  supercluster->m_hasEnoughTextToAutosize = NotEnoughText;
  return false;
}

float TextAutosizer::superclusterMultiplier(Cluster* cluster) {
  Supercluster* supercluster = cluster->m_supercluster;
  if (!supercluster->m_multiplier) {
    const LayoutBlock* widthProvider =
        maxClusterWidthProvider(cluster->m_supercluster, cluster->m_root);
    supercluster->m_multiplier =
        superclusterHasEnoughTextToAutosize(supercluster, widthProvider)
            ? multiplierFromBlock(widthProvider)
            : 1.0f;
  }
  ASSERT(supercluster->m_multiplier);
  return supercluster->m_multiplier;
}

const LayoutBlock* TextAutosizer::clusterWidthProvider(
    const LayoutBlock* root) const {
  if (root->isTable() || root->isTableCell())
    return root;

  return deepestBlockContainingAllText(root);
}

const LayoutBlock* TextAutosizer::maxClusterWidthProvider(
    const Supercluster* supercluster,
    const LayoutBlock* currentRoot) const {
  const LayoutBlock* result = clusterWidthProvider(currentRoot);
  float maxWidth = widthFromBlock(result);

  const BlockSet* roots = supercluster->m_roots;
  for (const auto* root : *roots) {
    const LayoutBlock* widthProvider = clusterWidthProvider(root);
    if (widthProvider->needsLayout())
      continue;
    float width = widthFromBlock(widthProvider);
    if (width > maxWidth) {
      maxWidth = width;
      result = widthProvider;
    }
  }
  RELEASE_ASSERT(result);
  return result;
}

float TextAutosizer::widthFromBlock(const LayoutBlock* block) const {
  RELEASE_ASSERT(block);
  RELEASE_ASSERT(block->style());

  if (!(block->isTable() || block->isTableCell() || block->isListItem()))
    return block->contentLogicalWidth().toFloat();

  if (!block->containingBlock())
    return 0;

  // Tables may be inflated before computing their preferred widths. Try several methods to
  // obtain a width, and fall back on a containing block's width.
  for (; block; block = block->containingBlock()) {
    float width;
    Length specifiedWidth =
        block->isTableCell()
            ? toLayoutTableCell(block)->styleOrColLogicalWidth()
            : block->style()->logicalWidth();
    if (specifiedWidth.isFixed()) {
      if ((width = specifiedWidth.value()) > 0)
        return width;
    }
    if (specifiedWidth.isPercentOrCalc()) {
      if (float containerWidth =
              block->containingBlock()->contentLogicalWidth().toFloat()) {
        if ((width = floatValueForLength(specifiedWidth, containerWidth)) > 0)
          return width;
      }
    }
    if ((width = block->contentLogicalWidth().toFloat()) > 0)
      return width;
  }
  return 0;
}

float TextAutosizer::multiplierFromBlock(const LayoutBlock* block) {
  // If block->needsLayout() is false, it does not need to be in m_blocksThatHaveBegunLayout.
  // This can happen during layout of a positioned object if the cluster's DBCAT is deeper
  // than the positioned object's containing block, and wasn't marked as needing layout.
  ASSERT(m_blocksThatHaveBegunLayout.contains(block) || !block->needsLayout());

  // Block width, in CSS pixels.
  float blockWidth = widthFromBlock(block);
  float layoutWidth =
      std::min(blockWidth, static_cast<float>(m_pageInfo.m_layoutWidth));
  float multiplier =
      m_pageInfo.m_frameWidth ? layoutWidth / m_pageInfo.m_frameWidth : 1.0f;
  multiplier *= m_pageInfo.m_accessibilityFontScaleFactor *
                m_pageInfo.m_deviceScaleAdjustment;
  return std::max(multiplier, 1.0f);
}

const LayoutBlock* TextAutosizer::deepestBlockContainingAllText(
    Cluster* cluster) {
  if (!cluster->m_deepestBlockContainingAllText)
    cluster->m_deepestBlockContainingAllText =
        deepestBlockContainingAllText(cluster->m_root);

  return cluster->m_deepestBlockContainingAllText;
}

// FIXME: Refactor this to look more like TextAutosizer::deepestCommonAncestor.
const LayoutBlock* TextAutosizer::deepestBlockContainingAllText(
    const LayoutBlock* root) const {
  size_t firstDepth = 0;
  const LayoutObject* firstTextLeaf = findTextLeaf(root, firstDepth, First);
  if (!firstTextLeaf)
    return root;

  size_t lastDepth = 0;
  const LayoutObject* lastTextLeaf = findTextLeaf(root, lastDepth, Last);
  ASSERT(lastTextLeaf);

  // Equalize the depths if necessary. Only one of the while loops below will get executed.
  const LayoutObject* firstNode = firstTextLeaf;
  const LayoutObject* lastNode = lastTextLeaf;
  while (firstDepth > lastDepth) {
    firstNode = firstNode->parent();
    --firstDepth;
  }
  while (lastDepth > firstDepth) {
    lastNode = lastNode->parent();
    --lastDepth;
  }

  // Go up from both nodes until the parent is the same. Both pointers will point to the LCA then.
  while (firstNode != lastNode) {
    firstNode = firstNode->parent();
    lastNode = lastNode->parent();
  }

  if (firstNode->isLayoutBlock())
    return toLayoutBlock(firstNode);

  // containingBlock() should never leave the cluster, since it only skips ancestors when finding
  // the container of position:absolute/fixed blocks, and those cannot exist between a cluster and
  // its text node's lowest common ancestor as isAutosizingCluster would have made them into their
  // own independent cluster.
  const LayoutBlock* containingBlock = firstNode->containingBlock();
  if (!containingBlock)
    return root;

  ASSERT(containingBlock->isDescendantOf(root));
  return containingBlock;
}

const LayoutObject* TextAutosizer::findTextLeaf(
    const LayoutObject* parent,
    size_t& depth,
    TextLeafSearch firstOrLast) const {
  // List items are treated as text due to the marker.
  if (parent->isListItem())
    return parent;

  if (parent->isText())
    return parent;

  ++depth;
  const LayoutObject* child = (firstOrLast == First) ? parent->slowFirstChild()
                                                     : parent->slowLastChild();
  while (child) {
    // Note: At this point clusters may not have been created for these blocks so we cannot rely
    //       on m_clusters. Instead, we use a best-guess about whether the block will become a cluster.
    if (!classifyBlock(child, INDEPENDENT)) {
      if (const LayoutObject* leaf = findTextLeaf(child, depth, firstOrLast))
        return leaf;
    }
    child = (firstOrLast == First) ? child->nextSibling()
                                   : child->previousSibling();
  }
  --depth;

  return nullptr;
}

void TextAutosizer::applyMultiplier(LayoutObject* layoutObject,
                                    float multiplier,
                                    SubtreeLayoutScope* layouter,
                                    RelayoutBehavior relayoutBehavior) {
  ASSERT(layoutObject);
  ComputedStyle& currentStyle = layoutObject->mutableStyleRef();
  if (!currentStyle.getTextSizeAdjust().isAuto()) {
    // The accessibility font scale factor is applied by the autosizer so we need to apply that
    // scale factor on top of the text-size-adjust multiplier.
    multiplier = currentStyle.getTextSizeAdjust().multiplier() *
                 m_pageInfo.m_accessibilityFontScaleFactor;
  } else if (multiplier < 1) {
    // Unlike text-size-adjust, the text autosizer should only inflate fonts.
    multiplier = 1;
  }

  if (currentStyle.textAutosizingMultiplier() == multiplier)
    return;

  // We need to clone the layoutObject style to avoid breaking style sharing.
  RefPtr<ComputedStyle> style = ComputedStyle::clone(currentStyle);
  style->setTextAutosizingMultiplier(multiplier);
  style->setUnique();

  switch (relayoutBehavior) {
    case AlreadyInLayout:
      // Don't free currentStyle until the end of the layout pass. This allows other parts of the system
      // to safely hold raw ComputedStyle* pointers during layout, e.g. BreakingContext::m_currentStyle.
      m_stylesRetainedDuringLayout.append(&currentStyle);

      layoutObject->setStyleInternal(style.release());
      DCHECK(!layouter || layoutObject->isDescendantOf(&layouter->root()));
      layoutObject->setNeedsLayoutAndFullPaintInvalidation(
          LayoutInvalidationReason::TextAutosizing, MarkContainerChain,
          layouter);
      break;

    case LayoutNeeded:
      DCHECK(!layouter);
      layoutObject->setStyle(style.release());
      break;
  }

  if (multiplier != 1)
    m_pageInfo.m_hasAutosized = true;

  layoutObject->clearBaseComputedStyle();
}

bool TextAutosizer::isWiderOrNarrowerDescendant(Cluster* cluster) {
  // FIXME: Why do we return true when hasExplicitWidth returns false??
  if (!cluster->m_parent || !hasExplicitWidth(cluster->m_root))
    return true;

  const LayoutBlock* parentDeepestBlockContainingAllText =
      deepestBlockContainingAllText(cluster->m_parent);
  ASSERT(m_blocksThatHaveBegunLayout.contains(cluster->m_root));
  ASSERT(m_blocksThatHaveBegunLayout.contains(
      parentDeepestBlockContainingAllText));

  float contentWidth = cluster->m_root->contentLogicalWidth().toFloat();
  float clusterTextWidth =
      parentDeepestBlockContainingAllText->contentLogicalWidth().toFloat();

  // Clusters with a root that is wider than the deepestBlockContainingAllText of their parent
  // autosize independently of their parent.
  if (contentWidth > clusterTextWidth)
    return true;

  // Clusters with a root that is significantly narrower than the deepestBlockContainingAllText of
  // their parent autosize independently of their parent.
  static float narrowWidthDifference = 200;
  if (clusterTextWidth - contentWidth > narrowWidthDifference)
    return true;

  return false;
}

TextAutosizer::Cluster* TextAutosizer::currentCluster() const {
  ASSERT_WITH_SECURITY_IMPLICATION(!m_clusterStack.isEmpty());
  return m_clusterStack.last().get();
}

TextAutosizer::Cluster::Cluster(const LayoutBlock* root,
                                BlockFlags flags,
                                Cluster* parent,
                                Supercluster* supercluster)
    : m_root(root),
      m_flags(flags),
      m_deepestBlockContainingAllText(nullptr),
      m_parent(parent),
      m_multiplier(0),
      m_hasEnoughTextToAutosize(UnknownAmountOfText),
      m_supercluster(supercluster),
      m_hasTableAncestor(root->isTableCell() ||
                         (m_parent && m_parent->m_hasTableAncestor)) {}

#if ENABLE(ASSERT)
void TextAutosizer::FingerprintMapper::assertMapsAreConsistent() {
  // For each fingerprint -> block mapping in m_blocksForFingerprint we should have an associated
  // map from block -> fingerprint in m_fingerprints.
  ReverseFingerprintMap::iterator end = m_blocksForFingerprint.end();
  for (ReverseFingerprintMap::iterator fingerprintIt =
           m_blocksForFingerprint.begin();
       fingerprintIt != end; ++fingerprintIt) {
    Fingerprint fingerprint = fingerprintIt->key;
    BlockSet* blocks = fingerprintIt->value.get();
    for (BlockSet::iterator blockIt = blocks->begin(); blockIt != blocks->end();
         ++blockIt) {
      const LayoutBlock* block = (*blockIt);
      ASSERT(m_fingerprints.get(block) == fingerprint);
    }
  }
}
#endif

void TextAutosizer::FingerprintMapper::add(const LayoutObject* layoutObject,
                                           Fingerprint fingerprint) {
  remove(layoutObject);

  m_fingerprints.set(layoutObject, fingerprint);
#if ENABLE(ASSERT)
  assertMapsAreConsistent();
#endif
}

void TextAutosizer::FingerprintMapper::addTentativeClusterRoot(
    const LayoutBlock* block,
    Fingerprint fingerprint) {
  add(block, fingerprint);

  ReverseFingerprintMap::AddResult addResult =
      m_blocksForFingerprint.add(fingerprint, std::unique_ptr<BlockSet>());
  if (addResult.isNewEntry)
    addResult.storedValue->value = wrapUnique(new BlockSet);
  addResult.storedValue->value->add(block);
#if ENABLE(ASSERT)
  assertMapsAreConsistent();
#endif
}

bool TextAutosizer::FingerprintMapper::remove(
    const LayoutObject* layoutObject) {
  Fingerprint fingerprint = m_fingerprints.take(layoutObject);
  if (!fingerprint || !layoutObject->isLayoutBlock())
    return false;

  ReverseFingerprintMap::iterator blocksIter =
      m_blocksForFingerprint.find(fingerprint);
  if (blocksIter == m_blocksForFingerprint.end())
    return false;

  BlockSet& blocks = *blocksIter->value;
  blocks.remove(toLayoutBlock(layoutObject));
  if (blocks.isEmpty())
    m_blocksForFingerprint.remove(blocksIter);
#if ENABLE(ASSERT)
  assertMapsAreConsistent();
#endif
  return true;
}

TextAutosizer::Fingerprint TextAutosizer::FingerprintMapper::get(
    const LayoutObject* layoutObject) {
  return m_fingerprints.get(layoutObject);
}

TextAutosizer::BlockSet*
TextAutosizer::FingerprintMapper::getTentativeClusterRoots(
    Fingerprint fingerprint) {
  return m_blocksForFingerprint.get(fingerprint);
}

TextAutosizer::LayoutScope::LayoutScope(LayoutBlock* block,
                                        SubtreeLayoutScope* layouter)
    : m_textAutosizer(block->document().textAutosizer()), m_block(block) {
  if (!m_textAutosizer)
    return;

  if (m_textAutosizer->shouldHandleLayout())
    m_textAutosizer->beginLayout(m_block, layouter);
  else
    m_textAutosizer = nullptr;
}

TextAutosizer::LayoutScope::~LayoutScope() {
  if (m_textAutosizer)
    m_textAutosizer->endLayout(m_block);
}

TextAutosizer::TableLayoutScope::TableLayoutScope(LayoutTable* table)
    : LayoutScope(table) {
  if (m_textAutosizer) {
    ASSERT(m_textAutosizer->shouldHandleLayout());
    m_textAutosizer->inflateAutoTable(table);
  }
}

TextAutosizer::DeferUpdatePageInfo::DeferUpdatePageInfo(Page* page)
    : m_mainFrame(page->deprecatedLocalMainFrame()) {
  if (TextAutosizer* textAutosizer = m_mainFrame->document()->textAutosizer()) {
    ASSERT(!textAutosizer->m_updatePageInfoDeferred);
    textAutosizer->m_updatePageInfoDeferred = true;
  }
}

TextAutosizer::DeferUpdatePageInfo::~DeferUpdatePageInfo() {
  if (TextAutosizer* textAutosizer = m_mainFrame->document()->textAutosizer()) {
    ASSERT(textAutosizer->m_updatePageInfoDeferred);
    textAutosizer->m_updatePageInfoDeferred = false;
    textAutosizer->updatePageInfoInAllFrames();
  }
}

float TextAutosizer::computeAutosizedFontSize(float specifiedSize,
                                              float multiplier) {
  DCHECK_GE(multiplier, 0);

  // Somewhat arbitrary "pleasant" font size.
  const float pleasantSize = 16;

  // Multiply fonts that the page author has specified to be larger than
  // pleasantSize by less and less, until huge fonts are not increased at all.
  // For specifiedSize between 0 and pleasantSize we directly apply the
  // multiplier; hence for specifiedSize == pleasantSize, computedSize will be
  // multiplier * pleasantSize. For greater specifiedSizes we want to
  // gradually fade out the multiplier, so for every 1px increase in
  // specifiedSize beyond pleasantSize we will only increase computedSize
  // by gradientAfterPleasantSize px until we meet the
  // computedSize = specifiedSize line, after which we stay on that line (so
  // then every 1px increase in specifiedSize increases computedSize by 1px).
  const float gradientAfterPleasantSize = 0.5;

  float computedSize;
  // Skip linear backoff for multipliers that shrink the size or when the font sizes are small.
  if (multiplier <= 1 || specifiedSize <= pleasantSize) {
    computedSize = multiplier * specifiedSize;
  } else {
    computedSize = multiplier * pleasantSize +
                   gradientAfterPleasantSize * (specifiedSize - pleasantSize);
    if (computedSize < specifiedSize)
      computedSize = specifiedSize;
  }
  return computedSize;
}

DEFINE_TRACE(TextAutosizer) {
  visitor->trace(m_document);
}

}  // namespace blink
