/*
 * This file is part of the WebKit project.
 *
 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
 *
 * 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"

#if ENABLE(SVG)
#include "SVGCharacterLayoutInfo.h"

#include "InlineFlowBox.h"
#include "InlineTextBox.h"
#include "SVGLengthList.h"
#include "SVGNumberList.h"
#include "SVGTextPositioningElement.h"
#include "RenderSVGTextPath.h"

#include <float.h>

namespace WebCore {

// Helper function
static float calculateBaselineShift(RenderObject* item)
{
    const Font& font = item->style()->font();
    const SVGRenderStyle* svgStyle = item->style()->svgStyle();

    float baselineShift = 0.0f;
    if (svgStyle->baselineShift() == BS_LENGTH) {
        CSSPrimitiveValue* primitive = static_cast<CSSPrimitiveValue*>(svgStyle->baselineShiftValue());
        baselineShift = primitive->getFloatValue();

        if (primitive->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
            baselineShift = baselineShift / 100.0f * font.pixelSize();
    } else {
        float baselineAscent = font.ascent() + font.descent();

        switch (svgStyle->baselineShift()) {
        case BS_BASELINE:
            break;
        case BS_SUB:
            baselineShift = -baselineAscent / 2.0f;
            break;
        case BS_SUPER:
            baselineShift = baselineAscent / 2.0f;
            break;
        default:
            ASSERT_NOT_REACHED();
        }
    }

    return baselineShift;
}

SVGCharacterLayoutInfo::SVGCharacterLayoutInfo(Vector<SVGChar>& chars)
    : curx(0.0f)
    , cury(0.0f)
    , angle(0.0f)
    , dx(0.0f)
    , dy(0.0f)
    , shiftx(0.0f)
    , shifty(0.0f)
    , pathExtraAdvance(0.0f)
    , pathTextLength(0.0f)
    , pathChunkLength(0.0f)
    , svgChars(chars)
    , nextDrawnSeperated(false)
    , xStackChanged(false)
    , yStackChanged(false)
    , dxStackChanged(false)
    , dyStackChanged(false)
    , angleStackChanged(false)
    , baselineShiftStackChanged(false)
    , pathLayout(false)
    , currentOffset(0.0f)
    , startOffset(0.0f)
    , layoutPathLength(0.0f)
{
}

bool SVGCharacterLayoutInfo::xValueAvailable() const
{
    return xStack.isEmpty() ? false : xStack.last().position() < xStack.last().size();
}

bool SVGCharacterLayoutInfo::yValueAvailable() const
{
    return yStack.isEmpty() ? false : yStack.last().position() < yStack.last().size();
}

bool SVGCharacterLayoutInfo::dxValueAvailable() const
{
    return dxStack.isEmpty() ? false : dxStack.last().position() < dxStack.last().size();
}

bool SVGCharacterLayoutInfo::dyValueAvailable() const
{
    return dyStack.isEmpty() ? false : dyStack.last().position() < dyStack.last().size();
}

bool SVGCharacterLayoutInfo::angleValueAvailable() const
{
    return angleStack.isEmpty() ? false : angleStack.last().position() < angleStack.last().size();
}

bool SVGCharacterLayoutInfo::baselineShiftValueAvailable() const
{
    return !baselineShiftStack.isEmpty();
}

float SVGCharacterLayoutInfo::xValueNext() const
{
    ASSERT(!xStack.isEmpty());
    return xStack.last().valueAtCurrentPosition();
}

float SVGCharacterLayoutInfo::yValueNext() const
{
    ASSERT(!yStack.isEmpty());
    return yStack.last().valueAtCurrentPosition();
}

float SVGCharacterLayoutInfo::dxValueNext() const
{
    ASSERT(!dxStack.isEmpty());
    return dxStack.last().valueAtCurrentPosition();
}

float SVGCharacterLayoutInfo::dyValueNext() const
{
    ASSERT(!dyStack.isEmpty());
    return dyStack.last().valueAtCurrentPosition();
}

float SVGCharacterLayoutInfo::angleValueNext() const
{
    ASSERT(!angleStack.isEmpty());
    return angleStack.last().valueAtCurrentPosition();
}

float SVGCharacterLayoutInfo::baselineShiftValueNext() const
{
    ASSERT(!baselineShiftStack.isEmpty());
    return baselineShiftStack.last();
}

void SVGCharacterLayoutInfo::processedSingleCharacter()
{
    xStackWalk();
    yStackWalk();
    dxStackWalk();
    dyStackWalk();
    angleStackWalk();
    baselineShiftStackWalk();
}

void SVGCharacterLayoutInfo::processedChunk(float savedShiftX, float savedShiftY)
{
    // baseline-shift doesn't span across ancestors, unlike dx/dy.
    curx += savedShiftX - shiftx;
    cury += savedShiftY - shifty;

    if (inPathLayout()) {
        shiftx = savedShiftX;
        shifty = savedShiftY;
    }

    // rotation also doesn't span
    angle = 0.0f;

    if (xStackChanged) {
        ASSERT(!xStack.isEmpty());
        xStack.removeLast();
        xStackChanged = false;
    }

    if (yStackChanged) {
        ASSERT(!yStack.isEmpty());
        yStack.removeLast();
        yStackChanged = false;
    }

    if (dxStackChanged) {
        ASSERT(!dxStack.isEmpty());
        dxStack.removeLast();
        dxStackChanged = false;
    }

    if (dyStackChanged) {
        ASSERT(!dyStack.isEmpty());
        dyStack.removeLast();
        dyStackChanged = false;
    }

    if (angleStackChanged) {
        ASSERT(!angleStack.isEmpty());
        angleStack.removeLast();
        angleStackChanged = false;
    }

    if (baselineShiftStackChanged) {
        ASSERT(!baselineShiftStack.isEmpty());
        baselineShiftStack.removeLast();
        baselineShiftStackChanged = false;
    }
}

bool SVGCharacterLayoutInfo::nextPathLayoutPointAndAngle(float glyphAdvance, float extraAdvance, float newOffset)
{
    if (layoutPathLength <= 0.0f)
        return false;

    if (newOffset != FLT_MIN)
        currentOffset = startOffset + newOffset;

    // Respect translation along path (extraAdvance is orthogonal to the path)
    currentOffset += extraAdvance;

    float offset = currentOffset + glyphAdvance / 2.0f;
    currentOffset += glyphAdvance + pathExtraAdvance;

    if (offset < 0.0f || offset > layoutPathLength)
        return false;

    bool ok = false; 
    FloatPoint point = layoutPath.pointAtLength(offset, ok);
    ASSERT(ok);

    curx = point.x();
    cury = point.y();

    angle = layoutPath.normalAngleAtLength(offset, ok);
    ASSERT(ok);

    // fprintf(stderr, "t: %f, x: %f, y: %f, angle: %f, glyphAdvance: %f\n", currentOffset, x, y, angle, glyphAdvance);
    return true;
}

bool SVGCharacterLayoutInfo::inPathLayout() const
{
    return pathLayout;
}

void SVGCharacterLayoutInfo::setInPathLayout(bool value)
{
    pathLayout = value;

    pathExtraAdvance = 0.0f;
    pathTextLength = 0.0f;
    pathChunkLength = 0.0f;
}

void SVGCharacterLayoutInfo::addLayoutInformation(InlineFlowBox* flowBox, float textAnchorStartOffset)
{
    bool isInitialLayout = xStack.isEmpty() && yStack.isEmpty() &&
                           dxStack.isEmpty() && dyStack.isEmpty() &&
                           angleStack.isEmpty() && baselineShiftStack.isEmpty() &&
                           curx == 0.0f && cury == 0.0f;

    RenderSVGTextPath* textPath = static_cast<RenderSVGTextPath*>(flowBox->object());
    Path path = textPath->layoutPath();

    float baselineShift = calculateBaselineShift(textPath);

    layoutPath = path;
    layoutPathLength = path.length();

    if (layoutPathLength <= 0.0f)
        return;

    startOffset = textPath->startOffset();

    if (textPath->startOffset() >= 0.0f && textPath->startOffset() <= 1.0f)
        startOffset *= layoutPathLength;

    startOffset += textAnchorStartOffset;
    currentOffset = startOffset;

    // Only baseline-shift is handled through the normal layout system
    addStackContent(BaselineShiftStack, baselineShift);

    if (isInitialLayout) {
        xStackChanged = false;
        yStackChanged = false;
        dxStackChanged = false;
        dyStackChanged = false;
        angleStackChanged = false;
        baselineShiftStackChanged = false;
    }
}

void SVGCharacterLayoutInfo::addLayoutInformation(SVGTextPositioningElement* element)
{
    bool isInitialLayout = xStack.isEmpty() && yStack.isEmpty() &&
                           dxStack.isEmpty() && dyStack.isEmpty() &&
                           angleStack.isEmpty() && baselineShiftStack.isEmpty() &&
                           curx == 0.0f && cury == 0.0f;

    float baselineShift = calculateBaselineShift(element->renderer());

    addStackContent(XStack, element->x());
    addStackContent(YStack, element->y());
    addStackContent(DxStack, element->dx());
    addStackContent(DyStack, element->dy());
    addStackContent(AngleStack, element->rotate());
    addStackContent(BaselineShiftStack, baselineShift);

    if (isInitialLayout) {
        xStackChanged = false;
        yStackChanged = false;
        dxStackChanged = false;
        dyStackChanged = false;
        angleStackChanged = false;
        baselineShiftStackChanged = false;
    }
}

void SVGCharacterLayoutInfo::addStackContent(StackType type, SVGNumberList* list)
{
    unsigned length = list->numberOfItems();
    if (!length)
        return;

    PositionedFloatVector newLayoutInfo;

    // TODO: Convert more efficiently!
    ExceptionCode ec = 0;
    for (unsigned i = 0; i < length; ++i) {
        float value = list->getItem(i, ec);
        ASSERT(ec == 0);

        newLayoutInfo.append(value);
    }

    addStackContent(type, newLayoutInfo);
}

void SVGCharacterLayoutInfo::addStackContent(StackType type, SVGLengthList* list)
{
    unsigned length = list->numberOfItems();
    if (!length)
        return;

    PositionedFloatVector newLayoutInfo;

    ExceptionCode ec = 0;
    for (unsigned i = 0; i < length; ++i) {
        float value = list->getItem(i, ec).value();
        ASSERT(ec == 0);

        newLayoutInfo.append(value);
    }

    addStackContent(type, newLayoutInfo);
}

void SVGCharacterLayoutInfo::addStackContent(StackType type, const PositionedFloatVector& list)
{
    switch (type) {
    case XStack:
        xStackChanged = true;
        xStack.append(list);
        break;
    case YStack:
        yStackChanged = true;
        yStack.append(list);
        break;
    case DxStack:
        dxStackChanged = true;
        dxStack.append(list);
        break;
    case DyStack:
        dyStackChanged = true;
        dyStack.append(list);
        break;
   case AngleStack:
        angleStackChanged = true;
        angleStack.append(list);
        break; 
   default:
        ASSERT_NOT_REACHED();
    }
}

void SVGCharacterLayoutInfo::addStackContent(StackType type, float value)
{
    if (value == 0.0f)
        return;

    switch (type) {
    case BaselineShiftStack:
        baselineShiftStackChanged = true;
        baselineShiftStack.append(value);
        break;
    default:
        ASSERT_NOT_REACHED();
    }
}

void SVGCharacterLayoutInfo::xStackWalk()
{
    unsigned i = 1;

    while (!xStack.isEmpty()) {
        PositionedFloatVector& cur = xStack.last();
        if (i + cur.position() < cur.size()) {
            cur.advance(i);
            break;
        }

        i += cur.position();
        xStack.removeLast();
        xStackChanged = false;
    }
}

void SVGCharacterLayoutInfo::yStackWalk()
{
    unsigned i = 1;

    while (!yStack.isEmpty()) {
        PositionedFloatVector& cur = yStack.last();
        if (i + cur.position() < cur.size()) {
            cur.advance(i);
            break;
        }

        i += cur.position();
        yStack.removeLast();
        yStackChanged = false;
    }
}

void SVGCharacterLayoutInfo::dxStackWalk()
{
    unsigned i = 1;

    while (!dxStack.isEmpty()) {
        PositionedFloatVector& cur = dxStack.last();
        if (i + cur.position() < cur.size()) {
            cur.advance(i);
            break;
        }

        i += cur.position();
        dxStack.removeLast();
        dxStackChanged = false;
    }
}

void SVGCharacterLayoutInfo::dyStackWalk()
{
    unsigned i = 1;

    while (!dyStack.isEmpty()) {
        PositionedFloatVector& cur = dyStack.last();
        if (i + cur.position() < cur.size()) {
            cur.advance(i);
            break;
        }

        i += cur.position();
        dyStack.removeLast();
        dyStackChanged = false;
    }
}

void SVGCharacterLayoutInfo::angleStackWalk()
{
    unsigned i = 1;

    while (!angleStack.isEmpty()) {
        PositionedFloatVector& cur = angleStack.last();
        if (i + cur.position() < cur.size()) {
            cur.advance(i);
            break;
        }

        i += cur.position();
        angleStack.removeLast();
        angleStackChanged = false;
    }
}

void SVGCharacterLayoutInfo::baselineShiftStackWalk()
{
    if (!baselineShiftStack.isEmpty()) {
        baselineShiftStack.removeLast();
        baselineShiftStackChanged = false;
    }
}

bool SVGChar::isHidden() const
{
    return pathData && pathData->hidden;
}

AffineTransform SVGChar::characterTransform() const
{
    AffineTransform ctm;

    // Rotate character around angle, and possibly scale.
    ctm.translate(x, y);
    ctm.rotate(angle);

    if (pathData) {
        ctm.scale(pathData->xScale, pathData->yScale);
        ctm.translate(pathData->xShift, pathData->yShift);
        ctm.rotate(pathData->orientationAngle);
    }

    ctm.translate(orientationShiftX - x, orientationShiftY - y);
    return ctm;
}

} // namespace WebCore

#endif // ENABLE(SVG)
