/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 * Copyright (C) 2012 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "core/rendering/TextAutosizer.h"

#include <algorithm>

#include "core/dom/Document.h"
#include "core/html/HTMLElement.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/frame/Settings.h"
#include "core/rendering/RenderListItem.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/RenderText.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/style/RenderStyle.h"
#include "core/rendering/style/StyleInheritedData.h"
#include "platform/TraceEvent.h"
#include "platform/geometry/IntSize.h"
#include "wtf/StdLibExtras.h"
#include "wtf/Vector.h"

namespace WebCore {

using namespace HTMLNames;

struct TextAutosizingWindowInfo {
    IntSize windowSize;
    IntSize minLayoutSize;
};

// Represents cluster related data. Instances should not persist between calls to processSubtree.
struct TextAutosizingClusterInfo {
    explicit TextAutosizingClusterInfo(RenderBlock* root)
        : root(root)
        , blockContainingAllText(0)
        , maxAllowedDifferenceFromTextWidth(150)
    {
    }

    RenderBlock* root;
    const RenderBlock* blockContainingAllText;

    // Upper limit on the difference between the width of the cluster's block containing all
    // text and that of a narrow child before the child becomes a separate cluster.
    float maxAllowedDifferenceFromTextWidth;

    // Descendants of the cluster that are narrower than the block containing all text and must be
    // processed together.
    Vector<TextAutosizingClusterInfo> narrowDescendants;
};

#ifdef AUTOSIZING_DOM_DEBUG_INFO
static void writeDebugInfo(RenderObject* renderObject, const AtomicString& output)
{
    Node* node = renderObject->node();
    if (node && node->isElementNode())
        toElement(node)->setAttribute("data-autosizing", output, ASSERT_NO_EXCEPTION);
}
#endif

static const Vector<QualifiedName>& formInputTags()
{
    // Returns the tags for the form input elements.
    DEFINE_STATIC_LOCAL(Vector<QualifiedName>, formInputTags, ());
    if (formInputTags.isEmpty()) {
        formInputTags.append(inputTag);
        formInputTags.append(buttonTag);
        formInputTags.append(selectTag);
    }
    return formInputTags;
}

static RenderListItem* getAncestorListItem(const RenderObject* renderer)
{
    RenderObject* ancestor = renderer->parent();
    while (ancestor && (ancestor->isRenderInline() || ancestor->isAnonymousBlock()))
        ancestor = ancestor->parent();

    return (ancestor && ancestor->isListItem()) ? toRenderListItem(ancestor) : 0;
}

static RenderObject* getAncestorList(const RenderObject* renderer)
{
    // FIXME: Add support for <menu> elements as a possible ancestor of an <li> element,
    // see http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#the-li-element
    for (RenderObject* ancestor = renderer->parent(); ancestor; ancestor = ancestor->parent()) {
        Node* parentNode = ancestor->generatingNode();
        if (parentNode && (parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag)))
            return ancestor;
    }
    return 0;
}

TextAutosizer::TextAutosizer(Document* document)
    : m_document(document)
{
}

void TextAutosizer::recalculateMultipliers()
{
    RenderObject* renderer = m_document->renderer();
    while (renderer) {
        if (renderer->style() && renderer->style()->textAutosizingMultiplier() != 1)
            setMultiplier(renderer, 1);
        renderer = renderer->nextInPreOrder();
    }
}

bool TextAutosizer::processSubtree(RenderObject* layoutRoot)
{
    TRACE_EVENT0("webkit", "TextAutosizer::processSubtree");

    if (!m_document->settings() || !m_document->settings()->textAutosizingEnabled() || layoutRoot->view()->document().printing() || !m_document->page())
        return false;

    Frame* mainFrame = m_document->page()->mainFrame();

    TextAutosizingWindowInfo windowInfo;

    // Window area, in logical (density-independent) pixels.
    windowInfo.windowSize = m_document->settings()->textAutosizingWindowSizeOverride();
    if (windowInfo.windowSize.isEmpty())
        windowInfo.windowSize = mainFrame->view()->unscaledVisibleContentSize(ScrollableArea::IncludeScrollbars);

    // Largest area of block that can be visible at once (assuming the main
    // frame doesn't get scaled to less than overview scale), in CSS pixels.
    windowInfo.minLayoutSize = mainFrame->view()->layoutSize();
    for (Frame* frame = m_document->frame(); frame; frame = frame->tree().parent())
        windowInfo.minLayoutSize = windowInfo.minLayoutSize.shrunkTo(frame->view()->layoutSize());

    // The layoutRoot could be neither a container nor a cluster, so walk up the tree till we find each of these.
    RenderBlock* container = layoutRoot->isRenderBlock() ? toRenderBlock(layoutRoot) : layoutRoot->containingBlock();
    while (container && !isAutosizingContainer(container))
        container = container->containingBlock();

    RenderBlock* cluster = container;
    while (cluster && (!isAutosizingContainer(cluster) || !isIndependentDescendant(cluster)))
        cluster = cluster->containingBlock();

    // Skip autosizing for orphaned trees, or if it will have no effect.
    // Note: this might suppress autosizing of an inner cluster with a different writing mode.
    // It's not clear what the correct behavior is for mixed writing modes anyway.
    if (!cluster || clusterMultiplier(cluster->style()->writingMode(), windowInfo,
        std::numeric_limits<float>::infinity()) == 1.0f)
        return false;

    TextAutosizingClusterInfo clusterInfo(cluster);
    processCluster(clusterInfo, container, layoutRoot, windowInfo);
    InspectorInstrumentation::didAutosizeText(layoutRoot);
    return true;
}

float TextAutosizer::clusterMultiplier(WritingMode writingMode, const TextAutosizingWindowInfo& windowInfo, float textWidth) const
{
    int logicalWindowWidth = isHorizontalWritingMode(writingMode) ? windowInfo.windowSize.width() : windowInfo.windowSize.height();
    int logicalLayoutWidth = isHorizontalWritingMode(writingMode) ? windowInfo.minLayoutSize.width() : windowInfo.minLayoutSize.height();
    // Ignore box width in excess of the layout width, to avoid extreme multipliers.
    float logicalClusterWidth = std::min<float>(textWidth, logicalLayoutWidth);

    float multiplier = logicalClusterWidth / logicalWindowWidth;
    multiplier *= m_document->settings()->accessibilityFontScaleFactor();

    // If the page has a meta viewport or @viewport, don't apply the device scale adjustment.
    const ViewportDescription& viewportDescription = m_document->page()->mainFrame()->document()->viewportDescription();
    if (!viewportDescription.isSpecifiedByAuthor()) {
        multiplier *= m_document->settings()->deviceScaleAdjustment();
    }
    return std::max(1.0f, multiplier);
}

void TextAutosizer::processClusterInternal(TextAutosizingClusterInfo& clusterInfo, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo, float multiplier)
{
    processContainer(multiplier, container, clusterInfo, subtreeRoot, windowInfo);
#ifdef AUTOSIZING_DOM_DEBUG_INFO
    writeDebugInfo(clusterInfo.root, String::format("cluster:%f", multiplier));
#endif

    Vector<Vector<TextAutosizingClusterInfo> > narrowDescendantsGroups;
    getNarrowDescendantsGroupedByWidth(clusterInfo, narrowDescendantsGroups);
    for (size_t i = 0; i < narrowDescendantsGroups.size(); ++i)
        processCompositeCluster(narrowDescendantsGroups[i], windowInfo);
}

void TextAutosizer::processCluster(TextAutosizingClusterInfo& clusterInfo, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
{
    // Many pages set a max-width on their content. So especially for the RenderView, instead of
    // just taking the width of |cluster| we find the lowest common ancestor of the first and last
    // descendant text node of the cluster (i.e. the deepest wrapper block that contains all the
    // text), and use its width instead.
    clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clusterInfo.root);
    float textWidth = clusterInfo.blockContainingAllText->contentLogicalWidth();
    float multiplier =  1.0;
    if (clusterShouldBeAutosized(clusterInfo, textWidth))
        multiplier = clusterMultiplier(clusterInfo.root->style()->writingMode(), windowInfo, textWidth);
    processClusterInternal(clusterInfo, container, subtreeRoot, windowInfo, multiplier);
}

void TextAutosizer::processCompositeCluster(Vector<TextAutosizingClusterInfo>& clusterInfos, const TextAutosizingWindowInfo& windowInfo)
{
    if (clusterInfos.isEmpty())
        return;

    float maxTextWidth = 0;
    for (size_t i = 0; i < clusterInfos.size(); ++i) {
        TextAutosizingClusterInfo& clusterInfo = clusterInfos[i];
        clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clusterInfo.root);
        maxTextWidth = max<float>(maxTextWidth, clusterInfo.blockContainingAllText->contentLogicalWidth());
    }

    float multiplier = 1.0;
    if (compositeClusterShouldBeAutosized(clusterInfos, maxTextWidth))
        multiplier = clusterMultiplier(clusterInfos[0].root->style()->writingMode(), windowInfo, maxTextWidth);
    for (size_t i = 0; i < clusterInfos.size(); ++i) {
        ASSERT(clusterInfos[i].root->style()->writingMode() == clusterInfos[0].root->style()->writingMode());
        processClusterInternal(clusterInfos[i], clusterInfos[i].root, clusterInfos[i].root, windowInfo, multiplier);
    }
}

void TextAutosizer::processContainer(float multiplier, RenderBlock* container, TextAutosizingClusterInfo& clusterInfo, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
{
    ASSERT(isAutosizingContainer(container));
#ifdef AUTOSIZING_DOM_DEBUG_INFO
    writeDebugInfo(container, "container");
#endif

    float localMultiplier = containerShouldBeAutosized(container) ? multiplier: 1;

    RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(subtreeRoot, subtreeRoot);
    while (descendant) {
        if (descendant->isText()) {
            if (localMultiplier != 1 && descendant->style()->textAutosizingMultiplier() == 1) {
                setMultiplier(descendant, localMultiplier);
                setMultiplier(descendant->parent(), localMultiplier); // Parent does line spacing.

                if (RenderListItem* listItemAncestor = getAncestorListItem(descendant)) {
                    if (RenderObject* list = getAncestorList(listItemAncestor)) {
                        if (list->style()->textAutosizingMultiplier() == 1)
                            setMultiplierForList(list, localMultiplier);
                    }
                }
            }
        } else if (isAutosizingContainer(descendant)) {
            RenderBlock* descendantBlock = toRenderBlock(descendant);
            TextAutosizingClusterInfo descendantClusterInfo(descendantBlock);
            if (isWiderDescendant(descendantBlock, clusterInfo) || isIndependentDescendant(descendantBlock))
                processCluster(descendantClusterInfo, descendantBlock, descendantBlock, windowInfo);
            else if (isNarrowDescendant(descendantBlock, clusterInfo)) {
                // Narrow descendants are processed together later to be able to apply the same multiplier
                // to each of them if necessary.
                clusterInfo.narrowDescendants.append(descendantClusterInfo);
            } else
                processContainer(multiplier, descendantBlock, clusterInfo, descendantBlock, windowInfo);
        }
        descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, subtreeRoot);
    }
}

void TextAutosizer::setMultiplier(RenderObject* renderer, float multiplier)
{
    RefPtr<RenderStyle> newStyle = RenderStyle::clone(renderer->style());
    newStyle->setTextAutosizingMultiplier(multiplier);
    newStyle->setUnique();
    renderer->setStyle(newStyle.release());
}

void TextAutosizer::setMultiplierForList(RenderObject* renderer, float multiplier)
{
#ifndef NDEBUG
    Node* parentNode = renderer->generatingNode();
    ASSERT(parentNode);
    ASSERT(parentNode->hasTagName(olTag) || parentNode->hasTagName(ulTag));
#endif
    setMultiplier(renderer, multiplier);

    // Make sure all list items are autosized consistently.
    for (RenderObject* child = renderer->firstChild(); child; child = child->nextSibling()) {
        if (child->isListItem() && child->style()->textAutosizingMultiplier() == 1)
            setMultiplier(child, multiplier);
    }
}

float TextAutosizer::computeAutosizedFontSize(float specifiedSize, float multiplier)
{
    // 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;
    if (specifiedSize <= pleasantSize)
        computedSize = multiplier * specifiedSize;
    else {
        computedSize = multiplier * pleasantSize + gradientAfterPleasantSize * (specifiedSize - pleasantSize);
        if (computedSize < specifiedSize)
            computedSize = specifiedSize;
    }
    return computedSize;
}

bool TextAutosizer::isAutosizingContainer(const RenderObject* renderer)
{
    // "Autosizing containers" are the smallest unit for which we can
    // enable/disable Text Autosizing.
    // - 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 list items, as items in the same list should look consistent (*).
    // - 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 = renderer->generatingNode();
    if ((node && !node->hasChildNodes())
        || !renderer->isRenderBlock()
        || (renderer->isInline() && !renderer->style()->isDisplayReplacedType()))
        return false;
    if (renderer->isListItem())
        return renderer->isFloating() || renderer->isOutOfFlowPositioned();
    // Avoid creating containers for text within text controls, buttons, or <select> buttons.
    Node* parentNode = renderer->parent() ? renderer->parent()->generatingNode() : 0;
    if (parentNode && parentNode->isElementNode() && formInputTags().contains(toElement(parentNode)->tagQName()))
        return false;

    return true;
}

bool TextAutosizer::isNarrowDescendant(const RenderBlock* renderer, TextAutosizingClusterInfo& parentClusterInfo)
{
    ASSERT(isAutosizingContainer(renderer));

    // Autosizing containers that are significantly narrower than the |blockContainingAllText| of
    // their enclosing cluster may be acting as separate columns, hence must be autosized
    // separately. For example the 2nd div in:
    // <body>
    //     <div style="float: right; width: 50%"></div>
    //     <div style="width: 50%"></div>
    // <body>
    // is the left column, and should be autosized differently from the body.
    // If however the container is only narrower by 150px or less, it's considered part of
    // the enclosing cluster. This 150px limit is adjusted whenever a descendant container is
    // less than 50px narrower than the current limit.
    const float differenceFromMaxWidthDifference = 50;
    float contentWidth = renderer->contentLogicalWidth();
    float clusterTextWidth = parentClusterInfo.blockContainingAllText->contentLogicalWidth();
    float widthDifference = clusterTextWidth - contentWidth;

    if (widthDifference - parentClusterInfo.maxAllowedDifferenceFromTextWidth > differenceFromMaxWidthDifference)
        return true;

    parentClusterInfo.maxAllowedDifferenceFromTextWidth = std::max(widthDifference, parentClusterInfo.maxAllowedDifferenceFromTextWidth);
    return false;
}

bool TextAutosizer::isWiderDescendant(const RenderBlock* renderer, const TextAutosizingClusterInfo& parentClusterInfo)
{
    ASSERT(isAutosizingContainer(renderer));

    // Autosizing containers that are wider than the |blockContainingAllText| of their enclosing
    // cluster are treated the same way as autosizing clusters to be autosized separately.
    float contentWidth = renderer->contentLogicalWidth();
    float clusterTextWidth = parentClusterInfo.blockContainingAllText->contentLogicalWidth();
    return contentWidth > clusterTextWidth;
}

bool TextAutosizer::isIndependentDescendant(const RenderBlock* renderer)
{
    ASSERT(isAutosizingContainer(renderer));

    // "Autosizing clusters" are special autosizing containers within which we
    // want to enforce a uniform text size multiplier, in the hopes of making
    // the major sections of the page look internally consistent.
    // All their descendants (including other autosizing containers) must share
    // the same multiplier, except for subtrees which are themselves clusters,
    // and some of their descendant containers might not be autosized at all
    // (for example if their height is constrained).
    // Additionally, clusterShouldBeAutosized requires each cluster to contain a
    // minimum amount of text, without which it won't be autosized.
    //
    // Clusters are chosen using very similar criteria to CSS flow roots, aka
    // block formatting contexts (http://w3.org/TR/css3-box/#flow-root), since
    // flow roots correspond to box containers that behave somewhat
    // independently from their parent (for example they don't overlap floats).
    // The definition of a flow root also conveniently includes most of the
    // ways that a box and its children can have significantly different width
    // from the box's parent (we want to avoid having significantly different
    // width blocks within a cluster, since the narrower blocks would end up
    // larger than would otherwise be necessary).
    return renderer->isRenderView()
        || renderer->isFloating()
        || renderer->isOutOfFlowPositioned()
        || renderer->isTableCell()
        || renderer->isTableCaption()
        || renderer->isFlexibleBoxIncludingDeprecated()
        || renderer->hasColumns()
        || renderer->containingBlock()->isHorizontalWritingMode() != renderer->isHorizontalWritingMode()
        || renderer->style()->isDisplayReplacedType()
        || renderer->isTextArea()
        || renderer->style()->userModify() != READ_ONLY;
    // FIXME: Tables need special handling to multiply all their columns by
    // the same amount even if they're different widths; so do hasColumns()
    // containers, and probably flexboxes...
}

bool TextAutosizer::isAutosizingCluster(const RenderBlock* renderer, TextAutosizingClusterInfo& parentClusterInfo)
{
    ASSERT(isAutosizingContainer(renderer));

    return isNarrowDescendant(renderer, parentClusterInfo)
        || isWiderDescendant(renderer, parentClusterInfo)
        || isIndependentDescendant(renderer);
}

bool TextAutosizer::containerShouldBeAutosized(const RenderBlock* container)
{
    if (containerContainsOneOfTags(container, formInputTags()))
        return false;

    if (containerIsRowOfLinks(container))
        return false;

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

    return !contentHeightIsConstrained(container);
}

bool TextAutosizer::containerContainsOneOfTags(const RenderBlock* container, const Vector<QualifiedName>& tags)
{
    const RenderObject* renderer = container;
    while (renderer) {
        const Node* rendererNode = renderer->node();
        if (rendererNode && rendererNode->isElementNode()) {
            if (tags.contains(toElement(rendererNode)->tagQName()))
                return true;
        }
        renderer = nextInPreOrderSkippingDescendantsOfContainers(renderer, container);
    }

    return false;
}

bool TextAutosizer::containerIsRowOfLinks(const RenderObject* container)
{
    // A "row of links" is a container for which holds:
    //  1. it should not contain non-link text elements longer than 3 characters
    //  2. it should contain min. 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;
    RenderObject* renderer = container->nextInPreOrder(container);
    float matchingFontSize = -1;

    while (renderer) {
        if (!isAutosizingContainer(renderer)) {
            if (renderer->isText() && toRenderText(renderer)->text().impl()->stripWhiteSpace()->length() > 3)
                return false;
            if (!renderer->isInline())
                return false;
            if (renderer->isBR())
                return false;
        }
        if (renderer->style()->isLink()) {
            if (matchingFontSize < 0)
                matchingFontSize = renderer->style()->specifiedFontSize();
            else {
                if (matchingFontSize != renderer->style()->specifiedFontSize())
                    return false;
            }

            linkCount++;
            // Skip traversing descendants of the link.
            renderer = renderer->nextInPreOrderAfterChildren(container);
        } else
            renderer = nextInPreOrderSkippingDescendantsOfContainers(renderer, container);
    }

    return (linkCount >= 3);
}

bool TextAutosizer::contentHeightIsConstrained(const RenderBlock* container)
{
    // 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 (; container; container = container->containingBlock()) {
        RenderStyle* style = container->style();
        if (style->overflowY() >= OSCROLL)
            return false;
        if (style->height().isSpecified() || style->maxHeight().isSpecified() || container->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 !container->isRoot() && !container->isBody();
        }
        if (container->isFloating())
            return false;
    }
    return false;
}

bool TextAutosizer::clusterShouldBeAutosized(TextAutosizingClusterInfo& clusterInfo, float blockWidth)
{
    Vector<TextAutosizingClusterInfo> clusterInfos(1, clusterInfo);
    return compositeClusterShouldBeAutosized(clusterInfos, blockWidth);
}

bool TextAutosizer::compositeClusterShouldBeAutosized(Vector<TextAutosizingClusterInfo>& clusterInfos, float blockWidth)
{
    // Don't autosize clusters that contain less than 4 lines of text (in
    // practice less lines are required, since measureDescendantTextWidth
    // assumes that characters are 1em wide, but most characters are narrower
    // than that, so we're overestimating their contribution to the linecount).
    //
    // This is to reduce the likelihood of autosizing things like headers and
    // footers, which can be quite visually distracting. The rationale is that
    // if a cluster contains very few lines of text then it's ok to have to zoom
    // in and pan from side to side to read each line, since if there are very
    // few lines of text you'll only need to pan across once or twice.
    //
    // An exception to the 4 lines of text are the textarea and contenteditable
    // clusters, which are always autosized by default (i.e. threated as if they
    // contain more than 4 lines of text). This is to ensure that the text does
    // not suddenly get autosized when the user enters more than 4 lines of text.
    float totalTextWidth = 0;
    const float minLinesOfText = 4;
    float minTextWidth = blockWidth * minLinesOfText;
    for (size_t i = 0; i < clusterInfos.size(); ++i) {
        if (clusterInfos[i].root->isTextArea() || (clusterInfos[i].root->style() && clusterInfos[i].root->style()->userModify() != READ_ONLY))
            return true;
        measureDescendantTextWidth(clusterInfos[i].blockContainingAllText, clusterInfos[i], minTextWidth, totalTextWidth);
        if (totalTextWidth >= minTextWidth)
            return true;
    }
    return false;
}

void TextAutosizer::measureDescendantTextWidth(const RenderBlock* container, TextAutosizingClusterInfo& clusterInfo, float minTextWidth, float& textWidth)
{
    bool skipLocalText = !containerShouldBeAutosized(container);

    RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(container, container);
    while (descendant) {
        if (!skipLocalText && descendant->isText()) {
            textWidth += toRenderText(descendant)->renderedTextLength() * descendant->style()->specifiedFontSize();
        } else if (isAutosizingContainer(descendant)) {
            RenderBlock* descendantBlock = toRenderBlock(descendant);
            if (!isAutosizingCluster(descendantBlock, clusterInfo))
                measureDescendantTextWidth(descendantBlock, clusterInfo, minTextWidth, textWidth);
        }
        if (textWidth >= minTextWidth)
            return;
        descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, container);
    }
}

RenderObject* TextAutosizer::nextInPreOrderSkippingDescendantsOfContainers(const RenderObject* current, const RenderObject* stayWithin)
{
    if (current == stayWithin || !isAutosizingContainer(current))
        return current->nextInPreOrder(stayWithin);
    return current->nextInPreOrderAfterChildren(stayWithin);
}

const RenderBlock* TextAutosizer::findDeepestBlockContainingAllText(const RenderBlock* cluster)
{
    size_t firstDepth = 0;
    const RenderObject* firstTextLeaf = findFirstTextLeafNotInCluster(cluster, firstDepth, FirstToLast);
    if (!firstTextLeaf)
        return cluster;

    size_t lastDepth = 0;
    const RenderObject* lastTextLeaf = findFirstTextLeafNotInCluster(cluster, lastDepth, LastToFirst);
    ASSERT(lastTextLeaf);

    // Equalize the depths if necessary. Only one of the while loops below will get executed.
    const RenderObject* firstNode = firstTextLeaf;
    const RenderObject* 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->isRenderBlock())
        return toRenderBlock(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
    // nodes lowest common ancestor as isAutosizingCluster would have made them into their own independent
    // cluster.
    RenderBlock* containingBlock = firstNode->containingBlock();
    ASSERT(containingBlock->isDescendantOf(cluster));

    return containingBlock;
}

const RenderObject* TextAutosizer::findFirstTextLeafNotInCluster(const RenderObject* parent, size_t& depth, TraversalDirection direction)
{
    if (parent->isEmpty())
        return parent->isText() ? parent : 0;

    ++depth;
    const RenderObject* child = (direction == FirstToLast) ? parent->firstChild() : parent->lastChild();
    while (child) {
        if (!isAutosizingContainer(child) || !isIndependentDescendant(toRenderBlock(child))) {
            const RenderObject* leaf = findFirstTextLeafNotInCluster(child, depth, direction);
            if (leaf)
                return leaf;
        }
        child = (direction == FirstToLast) ? child->nextSibling() : child->previousSibling();
    }
    --depth;

    return 0;
}

namespace {

// Compares the width of the specified cluster's roots in descending order.
bool clusterWiderThanComparisonFn(const TextAutosizingClusterInfo& first, const TextAutosizingClusterInfo& second)
{
    return first.root->contentLogicalWidth() > second.root->contentLogicalWidth();
}

} // namespace

void TextAutosizer::getNarrowDescendantsGroupedByWidth(const TextAutosizingClusterInfo& parentClusterInfo, Vector<Vector<TextAutosizingClusterInfo> >& groups)
{
    ASSERT(parentClusterInfo.blockContainingAllText);
    ASSERT(groups.isEmpty());

    Vector<TextAutosizingClusterInfo> clusterInfos(parentClusterInfo.narrowDescendants);
    if (clusterInfos.isEmpty())
        return;

    std::sort(clusterInfos.begin(), clusterInfos.end(), &clusterWiderThanComparisonFn);
    groups.grow(1);

    // If the width difference between two consecutive elements of |clusterInfos| is greater than
    // this empirically determined value, the next element should start a new group.
    const float maxWidthDifferenceWithinGroup = 100;
    for (size_t i = 0; i < clusterInfos.size(); ++i) {
        groups.last().append(clusterInfos[i]);

        if (i + 1 < clusterInfos.size()) {
            float currentWidth = clusterInfos[i].root->contentLogicalWidth();
            float nextWidth = clusterInfos[i + 1].root->contentLogicalWidth();
            if (currentWidth - nextWidth > maxWidthDifferenceWithinGroup)
                groups.grow(groups.size() + 1);
        }
    }
}

} // namespace WebCore
