Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc.  All rights reserved.
      3  * Copyright (C) 2008 Eric Seidel <eric (at) webkit.org>
      4  * Copyright (C) 2013 Google, Inc. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "config.h"
     29 #include "core/platform/graphics/Pattern.h"
     30 
     31 #include <v8.h>
     32 #include "SkCanvas.h"
     33 #include "SkColorShader.h"
     34 #include "SkShader.h"
     35 #include "core/platform/graphics/Image.h"
     36 
     37 namespace WebCore {
     38 
     39 Pattern::Pattern(PassRefPtr<Image> image, bool repeatX, bool repeatY)
     40     : m_tileImage(image)
     41     , m_repeatX(repeatX)
     42     , m_repeatY(repeatY)
     43     , m_externalMemoryAllocated(0)
     44 {
     45     ASSERT(m_tileImage);
     46 }
     47 
     48 Pattern::~Pattern()
     49 {
     50     if (m_externalMemoryAllocated)
     51         v8::V8::AdjustAmountOfExternalAllocatedMemory(-m_externalMemoryAllocated);
     52 }
     53 
     54 SkShader* Pattern::shader()
     55 {
     56     if (m_pattern)
     57         return m_pattern.get();
     58 
     59     RefPtr<NativeImageSkia> image = m_tileImage->nativeImageForCurrentFrame();
     60     // If we don't have a bitmap, return a transparent shader.
     61     if (!image)
     62         m_pattern = adoptRef(new SkColorShader(SK_ColorTRANSPARENT));
     63     else if (m_repeatX && m_repeatY)
     64         m_pattern = adoptRef(SkShader::CreateBitmapShader(image->bitmap(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
     65     else {
     66         // Skia does not have a "draw the tile only once" option. Clamp_TileMode
     67         // repeats the last line of the image after drawing one tile. To avoid
     68         // filling the space with arbitrary pixels, this workaround forces the
     69         // image to have a line of transparent pixels on the "repeated" edge(s),
     70         // thus causing extra space to be transparent filled.
     71         SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
     72         SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
     73         int expandW = m_repeatX ? 0 : 1;
     74         int expandH = m_repeatY ? 0 : 1;
     75 
     76         // Create a transparent bitmap 1 pixel wider and/or taller than the
     77         // original, then copy the orignal into it.
     78         // FIXME: Is there a better way to pad (not scale) an image in skia?
     79         SkBitmap bm2;
     80         bm2.setConfig(image->bitmap().config(), image->bitmap().width() + expandW, image->bitmap().height() + expandH);
     81         bm2.allocPixels();
     82         bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
     83         SkCanvas canvas(bm2);
     84         canvas.drawBitmap(image->bitmap(), 0, 0);
     85         bm2.setImmutable();
     86         m_pattern = adoptRef(SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY));
     87 
     88         // Clamp to int, since that's what the adjust function takes.
     89         m_externalMemoryAllocated = static_cast<int>(std::min(static_cast<size_t>(INT_MAX), bm2.getSafeSize()));
     90         v8::V8::AdjustAmountOfExternalAllocatedMemory(m_externalMemoryAllocated);
     91     }
     92     m_pattern->setLocalMatrix(m_patternSpaceTransformation);
     93     return m_pattern.get();
     94 }
     95 
     96 void Pattern::setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation)
     97 {
     98     m_patternSpaceTransformation = patternSpaceTransformation;
     99     if (m_pattern)
    100         m_pattern->setLocalMatrix(m_patternSpaceTransformation);
    101 }
    102 
    103 }
    104