15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc.  All rights reserved.
353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google, Inc. All rights reserved.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
1053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
1153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
1253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
1353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *    documentation and/or other materials provided with the distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
1553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
1653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
1953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/Pattern.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <v8.h>
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkCanvas.h"
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkColorShader.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkShader.h"
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/Image.h"
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)Pattern::Pattern(PassRefPtr<Image> image, bool repeatX, bool repeatY)
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    : m_tileImage(image)
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    , m_repeatX(repeatX)
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    , m_repeatY(repeatY)
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    , m_externalMemoryAllocated(0)
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ASSERT(m_tileImage);
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)Pattern::~Pattern()
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
50e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (m_externalMemoryAllocated)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::V8::AdjustAmountOfExternalAllocatedMemory(-m_externalMemoryAllocated);
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)SkShader* Pattern::shader()
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_pattern)
57e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return m_pattern.get();
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<NativeImageSkia> image = m_tileImage->nativeImageForCurrentFrame();
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we don't have a bitmap, return a transparent shader.
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!image)
62e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        m_pattern = adoptRef(new SkColorShader(SK_ColorTRANSPARENT));
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (m_repeatX && m_repeatY)
64e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        m_pattern = adoptRef(SkShader::CreateBitmapShader(image->bitmap(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Skia does not have a "draw the tile only once" option. Clamp_TileMode
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // repeats the last line of the image after drawing one tile. To avoid
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // filling the space with arbitrary pixels, this workaround forces the
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // image to have a line of transparent pixels on the "repeated" edge(s),
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // thus causing extra space to be transparent filled.
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int expandW = m_repeatX ? 0 : 1;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int expandH = m_repeatY ? 0 : 1;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Create a transparent bitmap 1 pixel wider and/or taller than the
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // original, then copy the orignal into it.
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: Is there a better way to pad (not scale) an image in skia?
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SkBitmap bm2;
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bm2.setConfig(image->bitmap().config(), image->bitmap().width() + expandW, image->bitmap().height() + expandH);
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bm2.allocPixels();
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SkCanvas canvas(bm2);
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        canvas.drawBitmap(image->bitmap(), 0, 0);
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bm2.setImmutable();
86e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        m_pattern = adoptRef(SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY));
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Clamp to int, since that's what the adjust function takes.
8953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        m_externalMemoryAllocated = static_cast<int>(std::min(static_cast<size_t>(INT_MAX), bm2.getSafeSize()));
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::V8::AdjustAmountOfExternalAllocatedMemory(m_externalMemoryAllocated);
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_pattern->setLocalMatrix(m_patternSpaceTransformation);
93e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return m_pattern.get();
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Pattern::setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_patternSpaceTransformation = patternSpaceTransformation;
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_pattern)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_pattern->setLocalMatrix(m_patternSpaceTransformation);
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
104