/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2007 David Smith (catfish.man@gmail.com)
 * Copyright (C) 2003-2011, 2017 Apple Inc. All rights reserved.
 * Copyright (C) Research In Motion Limited 2010. 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 "RenderTreeBuilderFirstLetter.h"

#include "FontCascade.h"
#include "RenderBlock.h"
#include "RenderButton.h"
#include "RenderInline.h"
#include "RenderRubyRun.h"
#include "RenderSVGText.h"
#include "RenderStyle.h"
#include "RenderTable.h"
#include "RenderTextFragment.h"
#include "RenderTreeBuilder.h"

namespace WebCore {

static RenderStyle styleForFirstLetter(const RenderBlock& firstLetterBlock, const RenderObject& firstLetterContainer)
{
    auto* containerFirstLetterStyle = firstLetterBlock.getCachedPseudoStyle(PseudoId::FirstLetter, &firstLetterContainer.firstLineStyle());
    // FIXME: There appears to be some path where we have a first letter renderer without first letter style.
    ASSERT(containerFirstLetterStyle);
    auto firstLetterStyle = RenderStyle::clone(containerFirstLetterStyle ? *containerFirstLetterStyle : firstLetterContainer.firstLineStyle());

    // If we have an initial letter drop that is >= 1, then we need to force floating to be on.
    if (firstLetterStyle.initialLetterDrop() >= 1 && !firstLetterStyle.isFloating())
        firstLetterStyle.setFloating(firstLetterStyle.isLeftToRightDirection() ? Float::Left : Float::Right);

    // We have to compute the correct font-size for the first-letter if it has an initial letter height set.
    auto* paragraph = firstLetterContainer.isRenderBlockFlow() ? &firstLetterContainer : firstLetterContainer.containingBlock();
    if (firstLetterStyle.initialLetterHeight() >= 1 && firstLetterStyle.fontMetrics().hasCapHeight() && paragraph->style().fontMetrics().hasCapHeight()) {
        // FIXME: For ideographic baselines, we want to go from line edge to line edge. This is equivalent to (N-1)*line-height + the font height.
        // We don't yet support ideographic baselines.
        // For an N-line first-letter and for alphabetic baselines, the cap-height of the first letter needs to equal (N-1)*line-height of paragraph lines + cap-height of the paragraph
        // Mathematically we can't rely on font-size, since font().height() doesn't necessarily match. For reliability, the best approach is simply to
        // compare the final measured cap-heights of the two fonts in order to get to the closest possible value.
        firstLetterStyle.setLineBoxContain({ LineBoxContain::InitialLetter });
        int lineHeight = paragraph->style().computedLineHeight();

        // Set the font to be one line too big and then ratchet back to get to a precise fit. We can't just set the desired font size based off font height metrics
        // because many fonts bake ascent into the font metrics. Therefore we have to look at actual measured cap height values in order to know when we have a good fit.
        auto newFontDescription = firstLetterStyle.fontDescription();
        float capRatio = firstLetterStyle.fontMetrics().floatCapHeight() / firstLetterStyle.computedFontPixelSize();
        float startingFontSize = ((firstLetterStyle.initialLetterHeight() - 1) * lineHeight + paragraph->style().fontMetrics().capHeight()) / capRatio;
        newFontDescription.setSpecifiedSize(startingFontSize);
        newFontDescription.setComputedSize(startingFontSize);
        firstLetterStyle.setFontDescription(WTFMove(newFontDescription));
        firstLetterStyle.fontCascade().update(firstLetterStyle.fontCascade().fontSelector());

        int desiredCapHeight = (firstLetterStyle.initialLetterHeight() - 1) * lineHeight + paragraph->style().fontMetrics().capHeight();
        int actualCapHeight = firstLetterStyle.fontMetrics().capHeight();
        while (actualCapHeight > desiredCapHeight) {
            auto newFontDescription = firstLetterStyle.fontDescription();
            newFontDescription.setSpecifiedSize(newFontDescription.specifiedSize() - 1);
            newFontDescription.setComputedSize(newFontDescription.computedSize() -1);
            firstLetterStyle.setFontDescription(WTFMove(newFontDescription));
            firstLetterStyle.fontCascade().update(firstLetterStyle.fontCascade().fontSelector());
            actualCapHeight = firstLetterStyle.fontMetrics().capHeight();
        }
    }

    // Force inline display (except for floating first-letters).
    firstLetterStyle.setDisplay(firstLetterStyle.isFloating() ? DisplayType::Block : DisplayType::Inline);
    // CSS2 says first-letter can't be positioned.
    firstLetterStyle.setPosition(PositionType::Static);
    return firstLetterStyle;
}

// CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter
// "Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps), "close" (Pe),
// "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that precedes or follows the first letter should be included"
static inline bool isPunctuationForFirstLetter(UChar32 c)
{
    return U_GET_GC_MASK(c) & (U_GC_PS_MASK | U_GC_PE_MASK | U_GC_PI_MASK | U_GC_PF_MASK | U_GC_PO_MASK);
}

static inline bool shouldSkipForFirstLetter(UChar32 c)
{
    return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
}

static bool supportsFirstLetter(RenderBlock& block)
{
    if (is<RenderButton>(block))
        return true;
    if (!is<RenderBlockFlow>(block))
        return false;
    if (is<RenderSVGText>(block))
        return false;
    if (is<RenderRubyRun>(block))
        return false;
    return block.canHaveGeneratedChildren();
}

RenderTreeBuilder::FirstLetter::FirstLetter(RenderTreeBuilder& builder)
    : m_builder(builder)
{
}

void RenderTreeBuilder::FirstLetter::updateAfterDescendants(RenderBlock& block)
{
    if (!block.style().hasPseudoStyle(PseudoId::FirstLetter))
        return;
    if (!supportsFirstLetter(block))
        return;

    // FIXME: This should be refactored, firstLetterContainer is not needed.
    RenderObject* firstLetterRenderer;
    RenderElement* firstLetterContainer;
    block.getFirstLetter(firstLetterRenderer, firstLetterContainer);

    if (!firstLetterRenderer)
        return;

    // Other containers are handled when updating their renderers.
    if (&block != firstLetterContainer)
        return;

    // If the child already has style, then it has already been created, so we just want
    // to update it.
    if (firstLetterRenderer->parent()->style().styleType() == PseudoId::FirstLetter) {
        updateStyle(block, *firstLetterRenderer);
        return;
    }

    if (!is<RenderText>(firstLetterRenderer))
        return;

    createRenderers(block, downcast<RenderText>(*firstLetterRenderer));
}

void RenderTreeBuilder::FirstLetter::cleanupOnDestroy(RenderTextFragment& textFragment)
{
    if (!textFragment.firstLetter())
        return;
    m_builder.destroy(*textFragment.firstLetter());
}

void RenderTreeBuilder::FirstLetter::updateStyle(RenderBlock& firstLetterBlock, RenderObject& currentChild)
{
    RenderElement* firstLetter = currentChild.parent();
    ASSERT(firstLetter->isFirstLetter());

    RenderElement* firstLetterContainer = firstLetter->parent();
    auto pseudoStyle = styleForFirstLetter(firstLetterBlock, *firstLetterContainer);
    ASSERT(firstLetter->isFloating() || firstLetter->isInline());

    if (Style::determineChange(firstLetter->style(), pseudoStyle) == Style::Detach) {
        // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
        RenderPtr<RenderBoxModelObject> newFirstLetter;
        if (pseudoStyle.display() == DisplayType::Inline)
            newFirstLetter = createRenderer<RenderInline>(firstLetterBlock.document(), WTFMove(pseudoStyle));
        else
            newFirstLetter = createRenderer<RenderBlockFlow>(firstLetterBlock.document(), WTFMove(pseudoStyle));
        newFirstLetter->initializeStyle();
        newFirstLetter->setIsFirstLetter();

        // Move the first letter into the new renderer.
        while (RenderObject* child = firstLetter->firstChild()) {
            if (is<RenderText>(*child))
                downcast<RenderText>(*child).removeAndDestroyTextBoxes();
            auto toMove = m_builder.detach(*firstLetter, *child);
            m_builder.attach(*newFirstLetter, WTFMove(toMove));
        }

        if (RenderTextFragment* remainingText = downcast<RenderBoxModelObject>(*firstLetter).firstLetterRemainingText()) {
            ASSERT(remainingText->isAnonymous() || remainingText->textNode()->renderer() == remainingText);
            // Replace the old renderer with the new one.
            remainingText->setFirstLetter(*newFirstLetter);
            newFirstLetter->setFirstLetterRemainingText(*remainingText);
        }
        WeakPtr<RenderObject> nextSibling = makeWeakPtr(firstLetter->nextSibling());
        m_builder.destroy(*firstLetter);
        m_builder.attach(*firstLetterContainer, WTFMove(newFirstLetter), nextSibling.get());
        return;
    }

    firstLetter->setStyle(WTFMove(pseudoStyle));
}

void RenderTreeBuilder::FirstLetter::createRenderers(RenderBlock& firstLetterBlock, RenderText& currentTextChild)
{
    RenderElement* textContentParent = currentTextChild.parent();
    RenderElement* firstLetterContainer = nullptr;
    if (auto* wrapperInlineForDisplayContents = currentTextChild.inlineWrapperForDisplayContents())
        firstLetterContainer = wrapperInlineForDisplayContents->parent();
    else
        firstLetterContainer = textContentParent;
    auto pseudoStyle = styleForFirstLetter(firstLetterBlock, *firstLetterContainer);
    RenderPtr<RenderBoxModelObject> newFirstLetter;
    if (pseudoStyle.display() == DisplayType::Inline)
        newFirstLetter = createRenderer<RenderInline>(firstLetterBlock.document(), WTFMove(pseudoStyle));
    else
        newFirstLetter = createRenderer<RenderBlockFlow>(firstLetterBlock.document(), WTFMove(pseudoStyle));
    newFirstLetter->initializeStyle();
    newFirstLetter->setIsFirstLetter();

    // The original string is going to be either a generated content string or a DOM node's
    // string. We want the original string before it got transformed in case first-letter has
    // no text-transform or a different text-transform applied to it.
    String oldText = currentTextChild.originalText();
    ASSERT(!oldText.isNull());

    if (!oldText.isEmpty()) {
        unsigned length = 0;

        // Account for leading spaces and punctuation.
        while (length < oldText.length() && shouldSkipForFirstLetter(oldText.characterStartingAt(length)))
            length += numCodeUnitsInGraphemeClusters(StringView(oldText).substring(length), 1);

        // Account for first grapheme cluster.
        length += numCodeUnitsInGraphemeClusters(StringView(oldText).substring(length), 1);

        // Keep looking for whitespace and allowed punctuation, but avoid
        // accumulating just whitespace into the :first-letter.
        unsigned numCodeUnits = 0;
        for (unsigned scanLength = length; scanLength < oldText.length(); scanLength += numCodeUnits) {
            UChar32 c = oldText.characterStartingAt(scanLength);

            if (!shouldSkipForFirstLetter(c))
                break;

            numCodeUnits = numCodeUnitsInGraphemeClusters(StringView(oldText).substring(scanLength), 1);

            if (isPunctuationForFirstLetter(c))
                length = scanLength + numCodeUnits;
        }

        auto* textNode = currentTextChild.textNode();
        auto* beforeChild = currentTextChild.nextSibling();
        auto inlineWrapperForDisplayContents = makeWeakPtr(currentTextChild.inlineWrapperForDisplayContents());
        auto hasInlineWrapperForDisplayContents = inlineWrapperForDisplayContents.get();
        m_builder.destroy(currentTextChild);

        // Construct a text fragment for the text after the first letter.
        // This text fragment might be empty.
        RenderPtr<RenderTextFragment> newRemainingText;
        if (textNode) {
            newRemainingText = createRenderer<RenderTextFragment>(*textNode, oldText, length, oldText.length() - length);
            textNode->setRenderer(newRemainingText.get());
        } else
            newRemainingText = createRenderer<RenderTextFragment>(firstLetterBlock.document(), oldText, length, oldText.length() - length);

        RenderTextFragment& remainingText = *newRemainingText;
        ASSERT_UNUSED(hasInlineWrapperForDisplayContents, hasInlineWrapperForDisplayContents == inlineWrapperForDisplayContents.get());
        remainingText.setInlineWrapperForDisplayContents(inlineWrapperForDisplayContents.get());
        m_builder.attach(*textContentParent, WTFMove(newRemainingText), beforeChild);

        // FIXME: Make attach the final step so that we don't need to keep firstLetter around.
        auto& firstLetter = *newFirstLetter;
        remainingText.setFirstLetter(firstLetter);
        firstLetter.setFirstLetterRemainingText(remainingText);
        m_builder.attach(*firstLetterContainer, WTFMove(newFirstLetter), &remainingText);

        // Construct text fragment for the first letter.
        auto letter = createRenderer<RenderTextFragment>(firstLetterBlock.document(), oldText, 0, length);
        m_builder.attach(firstLetter, WTFMove(letter));
    }
}

};
