1/*
2 * Copyright (C) 2010 University of Szeged
3 * Copyright (C) 2010 Zoltan Herczeg
4 * Copyright (C) 2011 Renata Hodovan (reni@webkit.org)
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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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
30#if ENABLE(FILTERS)
31#include "RenderSVGResourceFilterPrimitive.h"
32
33#include "SVGFEImage.h"
34#include "SVGFilterPrimitiveStandardAttributes.h"
35#include "SVGNames.h"
36
37namespace WebCore {
38
39RenderSVGResourceFilterPrimitive::RenderSVGResourceFilterPrimitive(SVGFilterPrimitiveStandardAttributes& filterPrimitiveElement, PassRef<RenderStyle> style)
40    : RenderSVGHiddenContainer(filterPrimitiveElement, WTF::move(style))
41{
42}
43
44SVGFilterPrimitiveStandardAttributes& RenderSVGResourceFilterPrimitive::filterPrimitiveElement() const
45{
46    return static_cast<SVGFilterPrimitiveStandardAttributes&>(RenderSVGHiddenContainer::element());
47}
48
49void RenderSVGResourceFilterPrimitive::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
50{
51    RenderSVGHiddenContainer::styleDidChange(diff, oldStyle);
52
53    RenderObject* filter = parent();
54    if (!filter)
55        return;
56    ASSERT(filter->isSVGResourceFilter());
57
58    if (diff == StyleDifferenceEqual || !oldStyle)
59        return;
60
61    const SVGRenderStyle& newStyle = style().svgStyle();
62    if (filterPrimitiveElement().hasTagName(SVGNames::feFloodTag)) {
63        if (newStyle.floodColor() != oldStyle->svgStyle().floodColor())
64            toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_colorAttr);
65        if (newStyle.floodOpacity() != oldStyle->svgStyle().floodOpacity())
66            toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_opacityAttr);
67    } else if (filterPrimitiveElement().hasTagName(SVGNames::feDiffuseLightingTag) || filterPrimitiveElement().hasTagName(SVGNames::feSpecularLightingTag)) {
68        if (newStyle.lightingColor() != oldStyle->svgStyle().lightingColor())
69            toRenderSVGResourceFilter(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr);
70    }
71}
72
73FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect* effect)
74{
75    SVGFilter* filter = toSVGFilter(&(effect->filter()));
76    ASSERT(filter);
77
78    // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect.
79    FloatRect subregion;
80    if (unsigned numberOfInputEffects = effect->inputEffects().size()) {
81        subregion = determineFilterPrimitiveSubregion(effect->inputEffect(0));
82        for (unsigned i = 1; i < numberOfInputEffects; ++i)
83            subregion.unite(determineFilterPrimitiveSubregion(effect->inputEffect(i)));
84    } else
85        subregion = filter->filterRegionInUserSpace();
86
87    // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>.
88    if (effect->filterEffectType() == FilterEffectTypeTile)
89        subregion = filter->filterRegionInUserSpace();
90
91    FloatRect effectBoundaries = effect->effectBoundaries();
92    if (effect->hasX())
93        subregion.setX(effectBoundaries.x());
94    if (effect->hasY())
95        subregion.setY(effectBoundaries.y());
96    if (effect->hasWidth())
97        subregion.setWidth(effectBoundaries.width());
98    if (effect->hasHeight())
99        subregion.setHeight(effectBoundaries.height());
100
101    effect->setFilterPrimitiveSubregion(subregion);
102
103    FloatRect absoluteSubregion = filter->absoluteTransform().mapRect(subregion);
104    FloatSize filterResolution = filter->filterResolution();
105    absoluteSubregion.scale(filterResolution.width(), filterResolution.height());
106
107    // Clip every filter effect to the filter region.
108    FloatRect absoluteScaledFilterRegion = filter->filterRegion();
109    absoluteScaledFilterRegion.scale(filterResolution.width(), filterResolution.height());
110    absoluteSubregion.intersect(absoluteScaledFilterRegion);
111
112    effect->setMaxEffectRect(absoluteSubregion);
113    return subregion;
114}
115
116} // namespace WebCore
117
118#endif // ENABLE(FILTERS)
119