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