/*
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 * Copyright (C) 2015 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 "SVGTextChunk.h"

#include "RenderSVGInlineText.h"
#include "SVGInlineTextBoxInlines.h"
#include "SVGTextContentElement.h"
#include "SVGTextFragment.h"

namespace WebCore {

SVGTextChunk::SVGTextChunk(const Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned first, unsigned limit)
{
    ASSERT(first < limit);
    ASSERT(limit <= lineLayoutBoxes.size());

    const SVGInlineTextBox* box = lineLayoutBoxes[first];
    const RenderStyle& style = box->renderer().style();
    const SVGRenderStyle& svgStyle = style.svgStyle();

    if (!style.isLeftToRightDirection())
        m_chunkStyle |= SVGTextChunk::RightToLeftText;

    if (style.isVerticalWritingMode())
        m_chunkStyle |= SVGTextChunk::VerticalText;
    
    switch (svgStyle.textAnchor()) {
    case TextAnchor::Start:
        break;
    case TextAnchor::Middle:
        m_chunkStyle |= MiddleAnchor;
        break;
    case TextAnchor::End:
        m_chunkStyle |= EndAnchor;
        break;
    }

    if (auto* textContentElement = SVGTextContentElement::elementFromRenderer(box->renderer().parent())) {
        SVGLengthContext lengthContext(textContentElement);
        m_desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);

        switch (textContentElement->lengthAdjust()) {
        case SVGLengthAdjustUnknown:
            break;
        case SVGLengthAdjustSpacing:
            m_chunkStyle |= LengthAdjustSpacing;
            break;
        case SVGLengthAdjustSpacingAndGlyphs:
            m_chunkStyle |= LengthAdjustSpacingAndGlyphs;
            break;
        }
    }

    m_boxes.append(&lineLayoutBoxes[first], limit - first);
}

unsigned SVGTextChunk::totalCharacters() const
{
    unsigned characters = 0;
    for (auto* box : m_boxes) {
        for (auto& fragment : box->textFragments())
            characters += fragment.length;
    }
    return characters;
}

float SVGTextChunk::totalLength() const
{
    const SVGTextFragment* firstFragment = nullptr;
    const SVGTextFragment* lastFragment = nullptr;

    for (auto* box : m_boxes) {
        auto& fragments = box->textFragments();
        if (fragments.size()) {
            firstFragment = &(*fragments.begin());
            break;
        }
    }

    for (auto it = m_boxes.rbegin(), end = m_boxes.rend(); it != end; ++it) {
        auto& fragments = (*it)->textFragments();
        if (fragments.size()) {
            lastFragment = &(*fragments.rbegin());
            break;
        }
    }

    ASSERT(!firstFragment == !lastFragment);
    if (!firstFragment)
        return 0;

    if (m_chunkStyle & VerticalText)
        return (lastFragment->y + lastFragment->height) - firstFragment->y;

    return (lastFragment->x + lastFragment->width) - firstFragment->x;
}

float SVGTextChunk::totalAnchorShift() const
{
    float length = totalLength();
    if (m_chunkStyle & MiddleAnchor)
        return -length / 2;
    if (m_chunkStyle & EndAnchor)
        return m_chunkStyle & RightToLeftText ? 0 : -length;
    return m_chunkStyle & RightToLeftText ? -length : 0;
}

void SVGTextChunk::layout(HashMap<SVGInlineTextBox*, AffineTransform>& textBoxTransformations) const
{
    if (hasDesiredTextLength()) {
        if (hasLengthAdjustSpacing())
            processTextLengthSpacingCorrection();
        else {
            ASSERT(hasLengthAdjustSpacingAndGlyphs());
            buildBoxTransformations(textBoxTransformations);
        }
    }

    if (hasTextAnchor())
        processTextAnchorCorrection();
}

void SVGTextChunk::processTextLengthSpacingCorrection() const
{
    float textLengthShift = (desiredTextLength() - totalLength()) / totalCharacters();
    bool isVerticalText = m_chunkStyle & VerticalText;
    unsigned atCharacter = 0;

    for (auto* box : m_boxes) {
        for (auto& fragment : box->textFragments()) {
            if (isVerticalText)
                fragment.y += textLengthShift * atCharacter;
            else
                fragment.x += textLengthShift * atCharacter;
            
            atCharacter += fragment.length;
        }
    }
}

void SVGTextChunk::buildBoxTransformations(HashMap<SVGInlineTextBox*, AffineTransform>& textBoxTransformations) const
{
    AffineTransform spacingAndGlyphsTransform;
    bool foundFirstFragment = false;

    for (auto* box : m_boxes) {
        if (!foundFirstFragment) {
            if (!boxSpacingAndGlyphsTransform(box, spacingAndGlyphsTransform))
                continue;
            foundFirstFragment = true;
        }

        textBoxTransformations.set(box, spacingAndGlyphsTransform);
    }
}

bool SVGTextChunk::boxSpacingAndGlyphsTransform(const SVGInlineTextBox* box, AffineTransform& spacingAndGlyphsTransform) const
{
    auto& fragments = box->textFragments();
    if (fragments.isEmpty())
        return false;

    const SVGTextFragment& fragment = fragments.first();
    float scale = desiredTextLength() / totalLength();

    spacingAndGlyphsTransform.translate(fragment.x, fragment.y);

    if (m_chunkStyle & VerticalText)
        spacingAndGlyphsTransform.scaleNonUniform(1, scale);
    else
        spacingAndGlyphsTransform.scaleNonUniform(scale, 1);

    spacingAndGlyphsTransform.translate(-fragment.x, -fragment.y);
    return true;
}

void SVGTextChunk::processTextAnchorCorrection() const
{
    float textAnchorShift = totalAnchorShift();
    bool isVerticalText = m_chunkStyle & VerticalText;

    for (auto* box : m_boxes) {
        for (auto& fragment : box->textFragments()) {
            if (isVerticalText)
                fragment.y += textAnchorShift;
            else
                fragment.x += textAnchorShift;
        }
    }
}

} // namespace WebCore
