15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 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 COMPUTER, INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
27a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/CrossfadeGeneratedImage.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
291e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatRect.h"
30a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContextStateSaver.h"
31a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/ImageBuffer.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std;
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CrossfadeGeneratedImage::CrossfadeGeneratedImage(Image* fromImage, Image* toImage, float percentage, IntSize crossfadeSize, const IntSize& size)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_fromImage(fromImage)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_toImage(toImage)
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_percentage(percentage)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_crossfadeSize(crossfadeSize)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_size = size;
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void CrossfadeGeneratedImage::drawCrossfade(GraphicsContext* context)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float inversePercentage = 1 - m_percentage;
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize fromImageSize = m_fromImage->size();
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize toImageSize = m_toImage->size();
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Draw nothing if either of the images hasn't loaded yet.
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_fromImage == Image::nullImage() || m_toImage == Image::nullImage())
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContextStateSaver stateSaver(*context);
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->clip(IntRect(IntPoint(), m_crossfadeSize));
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->beginTransparencyLayer(1);
615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Draw the image we're fading away from.
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->save();
64a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_crossfadeSize != fromImageSize) {
65a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        context->scale(FloatSize(
66a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            static_cast<float>(m_crossfadeSize.width()) / fromImageSize.width(),
67a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            static_cast<float>(m_crossfadeSize.height()) / fromImageSize.height()));
68a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->setAlpha(inversePercentage);
705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    context->drawImage(m_fromImage, IntPoint());
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->restore();
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Draw the image we're fading towards.
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->save();
75a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_crossfadeSize != toImageSize) {
76a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        context->scale(FloatSize(
77a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            static_cast<float>(m_crossfadeSize.width()) / toImageSize.width(),
78a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            static_cast<float>(m_crossfadeSize.height()) / toImageSize.height()));
79a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->setAlpha(m_percentage);
815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    context->drawImage(m_toImage, IntPoint(), CompositePlusLighter);
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->restore();
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
84c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    context->endLayer();
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
87a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void CrossfadeGeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, blink::WebBlendMode blendMode)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContextStateSaver stateSaver(*context);
903c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    context->setCompositeOperation(compositeOp, blendMode);
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->clip(dstRect);
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->translate(dstRect.x(), dstRect.y());
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (dstRect.size() != srcRect.size())
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()));
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    context->translate(-srcRect.x(), -srcRect.y());
965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    drawCrossfade(context);
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
100a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void CrossfadeGeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const FloatSize& scale, const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& dstRect, blink::WebBlendMode blendMode, const IntSize& repeatSpacing)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
102a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> imageBuffer = context->createCompatibleBuffer(m_size);
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!imageBuffer)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Fill with the cross-faded image.
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContext* graphicsContext = imageBuffer->context();
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    drawCrossfade(graphicsContext);
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Tile the image buffer into the context.
1111e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    imageBuffer->drawPattern(context, srcRect, scale, phase, compositeOp, dstRect, blendMode, repeatSpacing);
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
115