/*
 * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc.  All rights reserved.
 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2013 Google, 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 COMPUTER, INC. ``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 COMPUTER, INC. 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"
#include "core/platform/graphics/Pattern.h"

#include <v8.h>
#include "SkCanvas.h"
#include "SkColorShader.h"
#include "SkShader.h"
#include "core/platform/graphics/Image.h"
#include "core/platform/graphics/skia/SkiaUtils.h"

namespace WebCore {

Pattern::Pattern(PassRefPtr<Image> image, bool repeatX, bool repeatY)
    : m_repeatX(repeatX)
    , m_repeatY(repeatY)
    , m_externalMemoryAllocated(0)
{
    ASSERT(image);
    m_tileImage = image->nativeImageForCurrentFrame();
}

Pattern::~Pattern()
{
    if (m_externalMemoryAllocated)
        v8::V8::AdjustAmountOfExternalAllocatedMemory(-m_externalMemoryAllocated);
}

SkShader* Pattern::shader()
{
    if (m_pattern)
        return m_pattern.get();

    // If we don't have a bitmap, return a transparent shader.
    if (!m_tileImage)
        m_pattern = adoptRef(new SkColorShader(SK_ColorTRANSPARENT));
    else if (m_repeatX && m_repeatY)
        m_pattern = adoptRef(SkShader::CreateBitmapShader(m_tileImage->bitmap(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
    else {
        // Skia does not have a "draw the tile only once" option. Clamp_TileMode
        // repeats the last line of the image after drawing one tile. To avoid
        // filling the space with arbitrary pixels, this workaround forces the
        // image to have a line of transparent pixels on the "repeated" edge(s),
        // thus causing extra space to be transparent filled.
        SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
        SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
        int expandW = m_repeatX ? 0 : 1;
        int expandH = m_repeatY ? 0 : 1;

        // Create a transparent bitmap 1 pixel wider and/or taller than the
        // original, then copy the orignal into it.
        // FIXME: Is there a better way to pad (not scale) an image in skia?
        SkBitmap bm2;
        bm2.setConfig(m_tileImage->bitmap().config(), m_tileImage->bitmap().width() + expandW, m_tileImage->bitmap().height() + expandH);
        bm2.allocPixels();
        bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
        SkCanvas canvas(bm2);
        canvas.drawBitmap(m_tileImage->bitmap(), 0, 0);
        bm2.setImmutable();
        m_pattern = adoptRef(SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY));

        // Clamp to int, since that's what the adjust function takes.
        m_externalMemoryAllocated = static_cast<int>(std::min(static_cast<size_t>(INT_MAX), bm2.getSafeSize()));
        v8::V8::AdjustAmountOfExternalAllocatedMemory(m_externalMemoryAllocated);
    }
    m_pattern->setLocalMatrix(affineTransformToSkMatrix(m_patternSpaceTransformation));
    return m_pattern.get();
}

void Pattern::setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation)
{
    m_patternSpaceTransformation = patternSpaceTransformation;
    if (m_pattern)
        m_pattern->setLocalMatrix(affineTransformToSkMatrix(m_patternSpaceTransformation));
}

}
