/*
 * Copyright (C) 2013 Apple Inc. 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 APPLE INC. AND ITS 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 APPLE INC. OR ITS 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"
#include "TextPaintStyle.h"

#include "Frame.h"
#include "GraphicsContext.h"
#include "PaintInfo.h"
#include "RenderStyle.h"
#include "RenderText.h"
#include "RenderView.h"
#include "Settings.h"

namespace WebCore {

TextPaintStyle::TextPaintStyle(ColorSpace colorSpace)
    : colorSpace(colorSpace)
    , strokeWidth(0)
{
}

TextPaintStyle::TextPaintStyle(Color color, ColorSpace colorSpace)
    : colorSpace(colorSpace)
    , fillColor(color)
    , strokeColor(color)
    , strokeWidth(0)
{
}

static Color adjustColorForVisibilityOnBackground(Color textColor, Color backgroundColor)
{
    int d = differenceSquared(textColor, backgroundColor);
    // Semi-arbitrarily chose 65025 (255^2) value here after a few tests.
    if (d > 65025)
        return textColor;

    int distanceFromWhite = differenceSquared(textColor, Color::white);
    int distanceFromBlack = differenceSquared(textColor, Color::black);
    if (distanceFromWhite < distanceFromBlack)
        return textColor.dark();

    return textColor.light();
}

TextPaintStyle computeTextPaintStyle(const RenderText& renderer, const RenderStyle& lineStyle, const PaintInfo& paintInfo)
{
    TextPaintStyle paintStyle(lineStyle.colorSpace());

    paintStyle.strokeWidth = lineStyle.textStrokeWidth();

    if (paintInfo.forceBlackText()) {
        paintStyle.fillColor = Color::black;
        paintStyle.strokeColor = Color::black;
        paintStyle.emphasisMarkColor = Color::black;
        return paintStyle;
    }
    paintStyle.fillColor = lineStyle.visitedDependentColor(CSSPropertyWebkitTextFillColor);

    bool forceBackgroundToWhite = false;
    if (renderer.document().printing()) {
        if (lineStyle.printColorAdjust() == PrintColorAdjustEconomy)
            forceBackgroundToWhite = true;
        if (renderer.frame().settings().shouldPrintBackgrounds())
            forceBackgroundToWhite = false;
    }

    // Make the text fill color legible against a white background
    if (forceBackgroundToWhite)
        paintStyle.fillColor = adjustColorForVisibilityOnBackground(paintStyle.fillColor, Color::white);

    paintStyle.strokeColor = lineStyle.visitedDependentColor(CSSPropertyWebkitTextStrokeColor);

    // Make the text stroke color legible against a white background
    if (forceBackgroundToWhite)
        paintStyle.strokeColor = adjustColorForVisibilityOnBackground(paintStyle.strokeColor, Color::white);

    paintStyle.emphasisMarkColor = lineStyle.visitedDependentColor(CSSPropertyWebkitTextEmphasisColor);

    // Make the text stroke color legible against a white background
    if (forceBackgroundToWhite)
        paintStyle.emphasisMarkColor = adjustColorForVisibilityOnBackground(paintStyle.emphasisMarkColor, Color::white);

    return paintStyle;
}

TextPaintStyle computeTextSelectionPaintStyle(const TextPaintStyle& textPaintStyle, const RenderText& renderer, const RenderStyle& lineStyle, const PaintInfo& paintInfo, bool& paintSelectedTextOnly, bool& paintSelectedTextSeparately, const ShadowData*& selectionShadow)
{
    paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection);
    paintSelectedTextSeparately = false;
    const ShadowData* textShadow = paintInfo.forceBlackText() ? 0 : lineStyle.textShadow();

    TextPaintStyle selectionPaintStyle = textPaintStyle;

    selectionShadow = textShadow;
    Color foreground = paintInfo.forceBlackText() ? Color::black : renderer.selectionForegroundColor();
    if (foreground.isValid() && foreground != selectionPaintStyle.fillColor) {
        if (!paintSelectedTextOnly)
            paintSelectedTextSeparately = true;
        selectionPaintStyle.fillColor = foreground;
    }

    Color emphasisMarkForeground = paintInfo.forceBlackText() ? Color::black : renderer.selectionEmphasisMarkColor();
    if (emphasisMarkForeground.isValid() && emphasisMarkForeground != selectionPaintStyle.emphasisMarkColor) {
        if (!paintSelectedTextOnly)
            paintSelectedTextSeparately = true;
        selectionPaintStyle.emphasisMarkColor = emphasisMarkForeground;
    }

    if (RenderStyle* pseudoStyle = renderer.getCachedPseudoStyle(SELECTION)) {
        const ShadowData* shadow = paintInfo.forceBlackText() ? 0 : pseudoStyle->textShadow();
        if (shadow != selectionShadow) {
            if (!paintSelectedTextOnly)
                paintSelectedTextSeparately = true;
            selectionShadow = shadow;
        }

        float strokeWidth = pseudoStyle->textStrokeWidth();
        if (strokeWidth != selectionPaintStyle.strokeWidth) {
            if (!paintSelectedTextOnly)
                paintSelectedTextSeparately = true;
            selectionPaintStyle.strokeWidth = strokeWidth;
        }

        Color stroke = paintInfo.forceBlackText() ? Color::black : pseudoStyle->visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
        if (stroke != selectionPaintStyle.strokeColor) {
            if (!paintSelectedTextOnly)
                paintSelectedTextSeparately = true;
            selectionPaintStyle.strokeColor = stroke;
        }
    }
    return selectionPaintStyle;
}

void updateGraphicsContext(GraphicsContext& context, const TextPaintStyle& paintStyle, FillColorType fillColorType)
{
    TextDrawingModeFlags mode = context.textDrawingMode();
    if (paintStyle.strokeWidth > 0) {
        TextDrawingModeFlags newMode = mode | TextModeStroke;
        if (mode != newMode) {
            context.setTextDrawingMode(newMode);
            mode = newMode;
        }
    }
    
    Color fillColor = fillColorType == UseEmphasisMarkColor ? paintStyle.emphasisMarkColor : paintStyle.fillColor;
    if (mode & TextModeFill && (fillColor != context.fillColor() || paintStyle.colorSpace != context.fillColorSpace()))
        context.setFillColor(fillColor, paintStyle.colorSpace);

    if (mode & TextModeStroke) {
        if (paintStyle.strokeColor != context.strokeColor())
            context.setStrokeColor(paintStyle.strokeColor, paintStyle.colorSpace);
        if (paintStyle.strokeWidth != context.strokeThickness())
            context.setStrokeThickness(paintStyle.strokeWidth);
    }
}

}
