1f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)/*
2f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
3f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) *
4f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
5f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * modification, are permitted provided that the following conditions are
6f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * met:
7f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) *
8f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
9f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
10f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
11f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
12f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * in the documentation and/or other materials provided with the
13f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * distribution.
14f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
15f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
16f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * this software without specific prior written permission.
17f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) *
18f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) */
30f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
31f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "config.h"
32f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "core/rendering/style/ShadowList.h"
33f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
34f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "platform/geometry/FloatRect.h"
35f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "platform/geometry/LayoutRect.h"
36f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
37f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)namespace WebCore {
38f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
39f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)static inline void calculateShadowExtent(const ShadowList* shadowList, int additionalOutlineSize, int& shadowLeft, int& shadowRight, int& shadowTop, int& shadowBottom)
40f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){
41f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    ASSERT(shadowList);
42f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    size_t shadowCount = shadowList->shadows().size();
43f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    for (size_t i = 0; i < shadowCount; ++i) {
44f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        const ShadowData& shadow = shadowList->shadows()[i];
45f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        if (shadow.style() == Inset)
46f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)            continue;
47f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        int blurAndSpread = shadow.blur() + shadow.spread() + additionalOutlineSize;
48f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        shadowLeft = std::min(shadow.x() - blurAndSpread, shadowLeft);
49f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        shadowRight = std::max(shadow.x() + blurAndSpread, shadowRight);
50f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        shadowTop = std::min(shadow.y() - blurAndSpread, shadowTop);
51f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        shadowBottom = std::max(shadow.y() + blurAndSpread, shadowBottom);
52f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    }
53f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)}
54f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
55f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)void ShadowList::adjustRectForShadow(LayoutRect& rect, int additionalOutlineSize) const
56f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){
57f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    int shadowLeft = 0;
58f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    int shadowRight = 0;
59f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    int shadowTop = 0;
60f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    int shadowBottom = 0;
61f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom);
62f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
63f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    rect.move(shadowLeft, shadowTop);
64f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    rect.setWidth(rect.width() - shadowLeft + shadowRight);
65f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    rect.setHeight(rect.height() - shadowTop + shadowBottom);
66f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)}
67f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
68f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)void ShadowList::adjustRectForShadow(FloatRect& rect, int additionalOutlineSize) const
69f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){
70f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    int shadowLeft = 0;
71f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    int shadowRight = 0;
72f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    int shadowTop = 0;
73f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    int shadowBottom = 0;
74f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom);
75f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
76f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    rect.move(shadowLeft, shadowTop);
77f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    rect.setWidth(rect.width() - shadowLeft + shadowRight);
78f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    rect.setHeight(rect.height() - shadowTop + shadowBottom);
79f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)}
80f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
81f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)PassRefPtr<ShadowList> ShadowList::blend(const ShadowList* from, const ShadowList* to, double progress)
82f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){
83f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    size_t fromLength = from ? from->shadows().size() : 0;
84f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    size_t toLength = to ? to->shadows().size() : 0;
85f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    if (!fromLength && !toLength)
86f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        return 0;
87f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
88f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    ShadowDataVector shadows;
89f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
90f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    DEFINE_STATIC_LOCAL(ShadowData, defaultShadowData, (IntPoint(), 0, 0, Normal, Color::transparent));
91f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    DEFINE_STATIC_LOCAL(ShadowData, defaultInsetShadowData, (IntPoint(), 0, 0, Inset, Color::transparent));
92f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
93f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    size_t maxLength = std::max(fromLength, toLength);
94f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    for (size_t i = 0; i < maxLength; ++i) {
95f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        const ShadowData* fromShadow = i < fromLength ? &from->shadows()[i] : 0;
96f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        const ShadowData* toShadow = i < toLength ? &to->shadows()[i] : 0;
97f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        if (!fromShadow)
98f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)            fromShadow = toShadow->style() == Inset ? &defaultInsetShadowData : &defaultShadowData;
99f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        else if (!toShadow)
100f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)            toShadow = fromShadow->style() == Inset ? &defaultInsetShadowData : &defaultShadowData;
101f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        shadows.append(toShadow->blend(*fromShadow, progress));
102f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    }
103f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
104f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    return ShadowList::adopt(shadows);
105f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)}
106f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
107f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)} // namespace WebCore
108