/*
 * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved.
 * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 "config.h"

#if ENABLE(MATHML)

#include "RenderMathMLFraction.h"

#include "GraphicsContext.h"
#include "MathMLNames.h"
#include "PaintInfo.h"
#include "RenderText.h"

namespace WebCore {
    
using namespace MathMLNames;

static const float gHorizontalPad = 0.2f;
static const float gLineThin = 0.33f;
static const float gLineMedium = 1.f;
static const float gLineThick = 3.f;
static const float gFractionBarWidth = 0.05f;
static const float gDenominatorPad = 0.1f;

RenderMathMLFraction::RenderMathMLFraction(Element* fraction) 
    : RenderMathMLBlock(fraction)
    , m_lineThickness(gLineMedium)
{
    setChildrenInline(false);
}

void RenderMathMLFraction::updateFromElement()
{
    // FIXME: mfrac where bevelled=true will need to reorganize the descendants
    if (isEmpty()) 
        return;
    
    Element* fraction = static_cast<Element*>(node());
    
    RenderObject* numerator = firstChild();
    String nalign = fraction->getAttribute(MathMLNames::numalignAttr);
    if (equalIgnoringCase(nalign, "left"))
        numerator->style()->setTextAlign(LEFT);
    else if (equalIgnoringCase(nalign, "right"))
        numerator->style()->setTextAlign(RIGHT);
    else
        numerator->style()->setTextAlign(CENTER);
    
    RenderObject* denominator = numerator->nextSibling();
    if (!denominator)
        return;
    
    String dalign = fraction->getAttribute(MathMLNames::denomalignAttr);
    if (equalIgnoringCase(dalign, "left"))
        denominator->style()->setTextAlign(LEFT);
    else if (equalIgnoringCase(dalign, "right"))
        denominator->style()->setTextAlign(RIGHT);
    else
        denominator->style()->setTextAlign(CENTER);
    
    // FIXME: parse units
    String thickness = fraction->getAttribute(MathMLNames::linethicknessAttr);
    m_lineThickness = gLineMedium;
    if (equalIgnoringCase(thickness, "thin"))
        m_lineThickness = gLineThin;
    else if (equalIgnoringCase(thickness, "medium"))
        m_lineThickness = gLineMedium;
    else if (equalIgnoringCase(thickness, "thick"))
        m_lineThickness = gLineThick;
    else if (equalIgnoringCase(thickness, "0"))
        m_lineThickness = 0;

    // Update the style for the padding of the denominator for the line thickness
    lastChild()->style()->setPaddingTop(Length(static_cast<int>(m_lineThickness + style()->fontSize() * gDenominatorPad), Fixed));
}

void RenderMathMLFraction::addChild(RenderObject* child, RenderObject* beforeChild)
{
    RenderBlock* row = new (renderArena()) RenderMathMLBlock(node());
    RefPtr<RenderStyle> rowStyle = makeBlockStyle();
    
    rowStyle->setTextAlign(CENTER);
    Length pad(static_cast<int>(rowStyle->fontSize() * gHorizontalPad), Fixed);
    rowStyle->setPaddingLeft(pad);
    rowStyle->setPaddingRight(pad);
    
    // Only add padding for rows as denominators
    bool isNumerator = isEmpty();
    if (!isNumerator) 
        rowStyle->setPaddingTop(Length(2, Fixed));
    
    row->setStyle(rowStyle.release());
    RenderBlock::addChild(row, beforeChild);
    row->addChild(child);
    updateFromElement();
}

void RenderMathMLFraction::layout()
{
    updateFromElement();

    // Adjust the fraction line thickness for the zoom
    if (lastChild() && lastChild()->isRenderBlock())
        m_lineThickness *= ceilf(gFractionBarWidth * style()->fontSize());

    RenderBlock::layout();

}

void RenderMathMLFraction::paint(PaintInfo& info, int tx, int ty)
{
    RenderMathMLBlock::paint(info, tx, ty);
    if (info.context->paintingDisabled() || info.phase != PaintPhaseForeground)
        return;
    
    if (!firstChild() ||!m_lineThickness)
        return;

    int verticalOffset = 0;
    // The children are always RenderMathMLBlock instances
    if (firstChild()->isRenderMathMLBlock()) {
        int adjustForThickness = m_lineThickness > 1 ? int(m_lineThickness / 2) : 1;
        if (int(m_lineThickness) % 2 == 1)
            adjustForThickness++;
        RenderMathMLBlock* numerator = toRenderMathMLBlock(firstChild());
        if (numerator->isRenderMathMLRow())
            verticalOffset = numerator->offsetHeight() + adjustForThickness;
        else 
            verticalOffset = numerator->offsetHeight();        
    }
    
    tx += x();
    ty += y() + verticalOffset;
    
    info.context->save();
    
    info.context->setStrokeThickness(m_lineThickness);
    info.context->setStrokeStyle(SolidStroke);
    info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceSRGB);
    
    info.context->drawLine(IntPoint(tx, ty), IntPoint(tx + offsetWidth(), ty));
    
    info.context->restore();
}

int RenderMathMLFraction::baselinePosition(FontBaseline, bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const
{
    if (firstChild() && firstChild()->isRenderMathMLBlock()) {
        RenderMathMLBlock* numerator = toRenderMathMLBlock(firstChild());
        RenderStyle* refStyle = style();
        if (previousSibling())
            refStyle = previousSibling()->style();
        else if (nextSibling())
            refStyle = nextSibling()->style();
        int shift = int(ceil((refStyle->fontMetrics().xHeight() + 1) / 2));
        return numerator->offsetHeight() + shift;
    }
    return RenderBlock::baselinePosition(AlphabeticBaseline, firstLine, lineDirection, linePositionMode);
}

}


#endif // ENABLE(MATHML)
