15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008, 2009, 2010, 2012 Apple Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
27a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GradientGeneratedImage.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatRect.h"
30a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContextStateSaver.h"
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void GradientGeneratedImage::draw(GraphicsContext* destContext, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp, WebBlendMode blendMode)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContextStateSaver stateSaver(*destContext);
37591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    destContext->setCompositeOperation(compositeOp, blendMode);
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    destContext->clip(destRect);
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    destContext->translate(destRect.x(), destRect.y());
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (destRect.size() != srcRect.size())
415d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        destContext->scale(destRect.width() / srcRect.width(), destRect.height() / srcRect.height());
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    destContext->translate(-srcRect.x(), -srcRect.y());
435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    destContext->setFillGradient(m_gradient);
445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    destContext->fillRect(FloatRect(FloatPoint(), m_size));
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
47bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)void GradientGeneratedImage::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const FloatSize& scale,
48e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect, WebBlendMode blendMode, const IntSize& repeatSpacing)
49e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
50bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    float stepX = srcRect.width() + repeatSpacing.width();
51bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    float stepY = srcRect.height() + repeatSpacing.height();
52e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    int firstColumn = static_cast<int>(floorf((((destRect.x() - phase.x()) / scale.width()) - srcRect.x()) / srcRect.width()));
53e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    int firstRow = static_cast<int>(floorf((((destRect.y() - phase.y()) / scale.height())  - srcRect.y()) / srcRect.height()));
54e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    for (int i = firstColumn; ; ++i) {
55bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        float dstX = (srcRect.x() + i * stepX) * scale.width() + phase.x();
56e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        // assert that first column encroaches left edge of dstRect.
57e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        ASSERT(i > firstColumn || dstX <= destRect.x());
58e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        ASSERT(i == firstColumn || dstX > destRect.x());
59e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
60e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (dstX >= destRect.maxX())
61e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            break;
62e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        float dstMaxX = dstX + srcRect.width() * scale.width();
63e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (dstX < destRect.x())
64e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            dstX = destRect.x();
65e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (dstMaxX > destRect.maxX())
66e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            dstMaxX = destRect.maxX();
67e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (dstX >= dstMaxX)
68e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            continue;
69e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
70e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        FloatRect visibleSrcRect;
71e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        FloatRect tileDstRect;
72e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        tileDstRect.setX(dstX);
73e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        tileDstRect.setWidth(dstMaxX - dstX);
74bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        visibleSrcRect.setX((tileDstRect.x() - phase.x()) / scale.width() - i * stepX);
75e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        visibleSrcRect.setWidth(tileDstRect.width() / scale.width());
76e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
77e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        for (int j = firstRow; ; j++) {
78bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            float dstY = (srcRect.y() + j * stepY) * scale.height() + phase.y();
79e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            // assert that first row encroaches top edge of dstRect.
80e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            ASSERT(j > firstRow || dstY <= destRect.y());
81e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            ASSERT(j == firstRow || dstY > destRect.y());
82e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
83e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (dstY >= destRect.maxY())
84e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                break;
85e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            float dstMaxY = dstY + srcRect.height() * scale.height();
86e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (dstY < destRect.y())
87e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                dstY = destRect.y();
88e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (dstMaxY > destRect.maxY())
89e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                dstMaxY = destRect.maxY();
90e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (dstY >= dstMaxY)
91e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                continue;
92e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
93e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            tileDstRect.setY(dstY);
94e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            tileDstRect.setHeight(dstMaxY - dstY);
95bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            visibleSrcRect.setY((tileDstRect.y() - phase.y()) / scale.height() - j * stepY);
96e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            visibleSrcRect.setHeight(tileDstRect.height() / scale.height());
97e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            draw(destContext, tileDstRect, visibleSrcRect, compositeOp, blendMode);
98e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        }
99e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
100e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
101e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
102e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} // namespace blink
103