1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/*
2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2008 Google Inc. All rights reserved.
3635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
4635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Redistribution and use in source and binary forms, with or without
5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * modification, are permitted provided that the following conditions
6635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * are met:
7635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
8635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 1.  Redistributions of source code must retain the above copyright
9635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
10635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 2.  Redistributions in binary form must reproduce the above copyright
11635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     notice, this list of conditions and the following disclaimer in the
12635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     documentation and/or other materials provided with the distribution.
13635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     its contributors may be used to endorse or promote products derived
15635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     from this software without specific prior written permission.
16635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
17635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */
28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "config.h"
30635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Pattern.h"
31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#include "AffineTransform.h"
33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Image.h"
34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "NativeImageSkia.h"
35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "SkCanvas.h"
370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SkColor.h"
380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SkColorShader.h"
390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SkShader.h"
40635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectnamespace WebCore {
42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
435e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Blockvoid Pattern::platformDestroy()
44635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
45bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    SkSafeUnref(m_pattern);
465e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    m_pattern = 0;
475e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block}
485e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
498a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockPlatformPatternPtr Pattern::platformPattern(const AffineTransform& patternTransform)
505e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{
515e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    if (m_pattern)
525e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        return m_pattern;
535e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
54635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Note: patternTransform is ignored since it seems to be applied elsewhere
55635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // (when the pattern is used?). Applying it to the pattern (i.e.
56635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // shader->setLocalMatrix) results in a double transformation. This can be
57635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // seen, for instance, as an extra offset in:
58635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // LayoutTests/fast/canvas/patternfill-repeat.html
59635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // and expanded scale and skew in:
60635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // LayoutTests/svg/W3C-SVG-1.1/pservers-grad-06-b.svg
61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
62635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    SkBitmap* bm = m_tileImage->nativeImageForCurrentFrame();
630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // If we don't have a bitmap, return a transparent shader.
640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!bm)
655e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        m_pattern = new SkColorShader(SkColorSetARGB(0, 0, 0, 0));
660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
675e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    else if (m_repeatX && m_repeatY)
685e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        m_pattern = SkShader::CreateBitmapShader(*bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
69635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
705e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    else {
71635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
725e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        // Skia does not have a "draw the tile only once" option. Clamp_TileMode
735e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        // repeats the last line of the image after drawing one tile. To avoid
745e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        // filling the space with arbitrary pixels, this workaround forces the
755e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        // image to have a line of transparent pixels on the "repeated" edge(s),
765e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        // thus causing extra space to be transparent filled.
775e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
785e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
795e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        int expandW = m_repeatX ? 0 : 1;
805e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        int expandH = m_repeatY ? 0 : 1;
815e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
825e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        // Create a transparent bitmap 1 pixel wider and/or taller than the
835e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        // original, then copy the orignal into it.
845e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        // FIXME: Is there a better way to pad (not scale) an image in skia?
855e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        SkBitmap bm2;
865e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        bm2.setConfig(bm->config(), bm->width() + expandW, bm->height() + expandH);
875e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        bm2.allocPixels();
885e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
895e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        SkCanvas canvas(bm2);
905e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        canvas.drawBitmap(*bm, 0, 0);
915e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        m_pattern = SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY);
925e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    }
935e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    m_pattern->setLocalMatrix(m_patternSpaceTransformation);
945e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    return m_pattern;
955e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block}
965e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
975e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Blockvoid Pattern::setPlatformPatternSpaceTransform()
985e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block{
995e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    if (m_pattern)
1005e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        m_pattern->setLocalMatrix(m_patternSpaceTransformation);
101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} // namespace WebCore
104