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 "platform/graphics/Pattern.h"
     30 
     31 #include <v8.h>
     32 #include "SkCanvas.h"
     33 #include "SkColorShader.h"
     34 #include "platform/graphics/skia/SkiaUtils.h"
     35 
     36 
     37 namespace WebCore {
     38 
     39 Pattern::Pattern(PassRefPtr<Image> image, bool repeatX, bool repeatY)
     40     : m_repeatX(repeatX)
     41     , m_repeatY(repeatY)
     42     , m_externalMemoryAllocated(0)
     43 {
     44     if (image) {
     45         m_tileImage = image->nativeImageForCurrentFrame();
     46     }
     47 }
     48 
     49 Pattern::~Pattern()
     50 {
     51     if (m_externalMemoryAllocated)
     52         v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_externalMemoryAllocated);
     53 }
     54 
     55 SkShader* Pattern::shader()
     56 {
     57     if (m_pattern)
     58         return m_pattern.get();
     59 
     60     SkMatrix localMatrix = affineTransformToSkMatrix(m_patternSpaceTransformation);
     61 
     62     // If we don't have a bitmap, return a transparent shader.
     63     if (!m_tileImage)
     64         m_pattern = adoptRef(new SkColorShader(SK_ColorTRANSPARENT));
     65     else if (m_repeatX && m_repeatY)
     66         m_pattern = adoptRef(SkShader::CreateBitmapShader(m_tileImage->bitmap(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix));
     67     else {
     68         // Skia does not have a "draw the tile only once" option. Clamp_TileMode
     69         // repeats the last line of the image after drawing one tile. To avoid
     70         // filling the space with arbitrary pixels, this workaround forces the
     71         // image to have a line of transparent pixels on the "repeated" edge(s),
     72         // thus causing extra space to be transparent filled.
     73         SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
     74         SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
     75         int expandW = m_repeatX ? 0 : 1;
     76         int expandH = m_repeatY ? 0 : 1;
     77 
     78         // Create a transparent bitmap 1 pixel wider and/or taller than the
     79         // original, then copy the orignal into it.
     80         // FIXME: Is there a better way to pad (not scale) an image in skia?
     81         SkImageInfo info = m_tileImage->bitmap().info();
     82         info.fWidth += expandW;
     83         info.fHeight += expandH;
     84         // we explicitly require non-opaquness, since we are going to add a transparent strip.
     85         info.fAlphaType = kPremul_SkAlphaType;
     86 
     87         SkBitmap bm2;
     88         bm2.allocPixels(info);
     89         bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
     90         SkCanvas canvas(bm2);
     91         canvas.drawBitmap(m_tileImage->bitmap(), 0, 0);
     92         bm2.setImmutable();
     93         m_pattern = adoptRef(SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY, &localMatrix));
     94 
     95         // Clamp to int, since that's what the adjust function takes.
     96         m_externalMemoryAllocated = static_cast<int>(std::min(static_cast<size_t>(INT_MAX), bm2.getSafeSize()));
     97         v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(m_externalMemoryAllocated);
     98     }
     99     return m_pattern.get();
    100 }
    101 
    102 void Pattern::setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation)
    103 {
    104     m_patternSpaceTransformation = patternSpaceTransformation;
    105     if (m_pattern)
    106         m_pattern.clear();
    107 }
    108 
    109 }
    110