Commit 52254932 authored by fs@opera.com's avatar fs@opera.com

Map light-source oBB-relative coordinates to the user-space of the filter

The 'fePointLight' and 'feSpotLight' light-source elements for
'fe{Diffuse,Specular}Lighting' defines positions, and in the case of
the latter a 'look-at' point (implicit direction). When an SVG filter is
declared to use primitiveUnits=objectBoundingBox, these positions/points
needs to be mapped to the user-space of the filter.
This is achieved by adding a new method resolve3dPoint() to Filter, and
perform the coordinate space mapping when creating the various
LightSources.
Open-code SVGFELightElement::findLightSource() in it's sources to avoid
passing the Filter-instance around more than necessary.

BUG=176419

Review URL: https://codereview.chromium.org/337903003

git-svn-id: svn://svn.chromium.org/blink/trunk@176499 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent eb26e520
......@@ -1109,6 +1109,9 @@ crbug.com/374936 [ Mac ] svg/dynamic-updates/SVGImageElement-dom-width-attr.html
crbug.com/374936 [ Mac ] svg/dynamic-updates/SVGImageElement-svgdom-height-prop.html [ ImageOnlyFailure Pass ]
crbug.com/374936 [ Mac ] svg/dynamic-updates/SVGImageElement-svgdom-width-prop.html [ ImageOnlyFailure Pass ]
crbug.com/176419 svg/dynamic-updates/SVGFilterElement-dom-primitiveUnits-attr.html [ NeedsRebaseline ]
crbug.com/176419 svg/dynamic-updates/SVGFilterElement-svgdom-primitiveUnits-prop.html [ NeedsRebaseline ]
crbug.com/313438 svg/custom/relative-sized-use-on-symbol.xhtml [ NeedsManualRebaseline ]
crbug.com/313438 svg/custom/relative-sized-use-without-attributes-on-symbol.xhtml [ NeedsManualRebaseline ]
......
<!DOCTYPE html>
<svg width="200" height="200">
<filter id="puusu" primitiveUnits="userSpaceOnUse" x="0" y="0" width="1" height="1">
<feDiffuseLighting>
<fePointLight x="100" y="100" z="20"/>
</feDiffuseLighting>
</filter>
<rect x="50" y="50" width="100" height="100" filter="url(#puusu)"/>
</svg>
<!DOCTYPE html>
<svg width="200" height="200">
<filter id="puobb" primitiveUnits="objectBoundingBox" x="0" y="0" width="1" height="1">
<feDiffuseLighting>
<fePointLight x="0.5" y="0.5" z="0.2"/>
</feDiffuseLighting>
</filter>
<rect x="50" y="50" width="100" height="100" filter="url(#puobb)"/>
</svg>
<!DOCTYPE html>
<svg width="200" height="200">
<filter id="puusu" primitiveUnits="userSpaceOnUse" x="0" y="0" width="1" height="1">
<feDiffuseLighting>
<feSpotLight x="100" y="100" z="40" pointsAtX="100" pointsAtY="100" pointsAtZ="20"/>
</feDiffuseLighting>
</filter>
<rect x="50" y="50" width="100" height="100" filter="url(#puusu)"/>
</svg>
<!DOCTYPE html>
<svg width="200" height="200">
<filter id="puobb" primitiveUnits="objectBoundingBox" x="0" y="0" width="1" height="1">
<feDiffuseLighting>
<feSpotLight x="0.5" y="0.5" z="0.4" pointsAtX="0.5" pointsAtY="0.5" pointsAtZ="0.2"/>
</feDiffuseLighting>
</filter>
<rect x="50" y="50" width="100" height="100" filter="url(#puobb)"/>
</svg>
......@@ -168,8 +168,8 @@ PassRefPtr<FilterEffect> SVGFEDiffuseLightingElement::build(SVGFilterBuilder* fi
if (!input1)
return nullptr;
RefPtr<LightSource> lightSource = SVGFELightElement::findLightSource(*this);
if (!lightSource)
SVGFELightElement* lightNode = SVGFELightElement::findLightElement(*this);
if (!lightNode)
return nullptr;
RenderObject* renderer = this->renderer();
......@@ -179,6 +179,7 @@ PassRefPtr<FilterEffect> SVGFEDiffuseLightingElement::build(SVGFilterBuilder* fi
ASSERT(renderer->style());
Color color = renderer->style()->svgStyle()->lightingColor();
RefPtr<LightSource> lightSource = lightNode->lightSource(filter);
RefPtr<FilterEffect> effect = FEDiffuseLighting::create(filter, color, m_surfaceScale->currentValue()->value(), m_diffuseConstant->currentValue()->value(),
kernelUnitLengthX()->currentValue()->value(), kernelUnitLengthY()->currentValue()->value(), lightSource.release());
effect->inputEffects().append(input1);
......
......@@ -33,7 +33,7 @@ inline SVGFEDistantLightElement::SVGFEDistantLightElement(Document& document)
DEFINE_NODE_FACTORY(SVGFEDistantLightElement)
PassRefPtr<LightSource> SVGFEDistantLightElement::lightSource() const
PassRefPtr<LightSource> SVGFEDistantLightElement::lightSource(Filter* filter) const
{
return DistantLightSource::create(azimuth()->currentValue()->value(), elevation()->currentValue()->value());
}
......
......@@ -31,7 +31,7 @@ public:
private:
explicit SVGFEDistantLightElement(Document&);
virtual PassRefPtr<LightSource> lightSource() const OVERRIDE;
virtual PassRefPtr<LightSource> lightSource(Filter*) const OVERRIDE;
};
} // namespace WebCore
......
......@@ -61,14 +61,6 @@ SVGFELightElement* SVGFELightElement::findLightElement(const SVGElement& svgElem
return Traversal<SVGFELightElement>::firstChild(svgElement);
}
PassRefPtr<LightSource> SVGFELightElement::findLightSource(const SVGElement& svgElement)
{
SVGFELightElement* lightNode = findLightElement(svgElement);
if (!lightNode)
return nullptr;
return lightNode->lightSource();
}
bool SVGFELightElement::isSupportedAttribute(const QualifiedName& attrName)
{
DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
......
......@@ -29,11 +29,12 @@
namespace WebCore {
class Filter;
class SVGFELightElement : public SVGElement {
public:
virtual PassRefPtr<LightSource> lightSource() const = 0;
virtual PassRefPtr<LightSource> lightSource(Filter*) const = 0;
static SVGFELightElement* findLightElement(const SVGElement&);
static PassRefPtr<LightSource> findLightSource(const SVGElement&);
SVGAnimatedNumber* azimuth() { return m_azimuth.get(); }
const SVGAnimatedNumber* azimuth() const { return m_azimuth.get(); }
......
......@@ -21,6 +21,7 @@
#include "core/svg/SVGFEPointLightElement.h"
#include "core/SVGNames.h"
#include "platform/graphics/filters/Filter.h"
#include "platform/graphics/filters/PointLightSource.h"
namespace WebCore {
......@@ -33,9 +34,10 @@ inline SVGFEPointLightElement::SVGFEPointLightElement(Document& document)
DEFINE_NODE_FACTORY(SVGFEPointLightElement)
PassRefPtr<LightSource> SVGFEPointLightElement::lightSource() const
PassRefPtr<LightSource> SVGFEPointLightElement::lightSource(Filter* filter) const
{
return PointLightSource::create(FloatPoint3D(x()->currentValue()->value(), y()->currentValue()->value(), z()->currentValue()->value()));
FloatPoint3D location(x()->currentValue()->value(), y()->currentValue()->value(), z()->currentValue()->value());
return PointLightSource::create(filter->resolve3dPoint(location));
}
}
......@@ -31,7 +31,7 @@ public:
private:
explicit SVGFEPointLightElement(Document&);
virtual PassRefPtr<LightSource> lightSource() const OVERRIDE;
virtual PassRefPtr<LightSource> lightSource(Filter*) const OVERRIDE;
};
} // namespace WebCore
......
......@@ -175,8 +175,8 @@ PassRefPtr<FilterEffect> SVGFESpecularLightingElement::build(SVGFilterBuilder* f
if (!input1)
return nullptr;
RefPtr<LightSource> lightSource = SVGFELightElement::findLightSource(*this);
if (!lightSource)
SVGFELightElement* lightNode = SVGFELightElement::findLightElement(*this);
if (!lightNode)
return nullptr;
RenderObject* renderer = this->renderer();
......@@ -186,6 +186,7 @@ PassRefPtr<FilterEffect> SVGFESpecularLightingElement::build(SVGFilterBuilder* f
ASSERT(renderer->style());
Color color = renderer->style()->svgStyle()->lightingColor();
RefPtr<LightSource> lightSource = lightNode->lightSource(filter);
RefPtr<FilterEffect> effect = FESpecularLighting::create(filter, color, m_surfaceScale->currentValue()->value(), m_specularConstant->currentValue()->value(),
m_specularExponent->currentValue()->value(), kernelUnitLengthX()->currentValue()->value(), kernelUnitLengthY()->currentValue()->value(), lightSource.release());
effect->inputEffects().append(input1);
......
......@@ -21,6 +21,7 @@
#include "core/svg/SVGFESpotLightElement.h"
#include "core/SVGNames.h"
#include "platform/graphics/filters/Filter.h"
#include "platform/graphics/filters/SpotLightSource.h"
namespace WebCore {
......@@ -33,12 +34,12 @@ inline SVGFESpotLightElement::SVGFESpotLightElement(Document& document)
DEFINE_NODE_FACTORY(SVGFESpotLightElement)
PassRefPtr<LightSource> SVGFESpotLightElement::lightSource() const
PassRefPtr<LightSource> SVGFESpotLightElement::lightSource(Filter* filter) const
{
FloatPoint3D pos(x()->currentValue()->value(), y()->currentValue()->value(), z()->currentValue()->value());
FloatPoint3D direction(pointsAtX()->currentValue()->value(), pointsAtY()->currentValue()->value(), pointsAtZ()->currentValue()->value());
return SpotLightSource::create(pos, direction, specularExponent()->currentValue()->value(), limitingConeAngle()->currentValue()->value());
return SpotLightSource::create(filter->resolve3dPoint(pos), filter->resolve3dPoint(direction), specularExponent()->currentValue()->value(), limitingConeAngle()->currentValue()->value());
}
}
......@@ -31,7 +31,7 @@ public:
private:
explicit SVGFESpotLightElement(Document&);
virtual PassRefPtr<LightSource> lightSource() const OVERRIDE;
virtual PassRefPtr<LightSource> lightSource(Filter*) const OVERRIDE;
};
} // namespace WebCore
......
......@@ -48,6 +48,15 @@ float SVGFilter::applyVerticalScale(float value) const
return Filter::applyVerticalScale(value);
}
FloatPoint3D SVGFilter::resolve3dPoint(const FloatPoint3D& point) const
{
if (!m_effectBBoxMode)
return point;
return FloatPoint3D(point.x() * m_targetBoundingBox.width() + m_targetBoundingBox.x(),
point.y() * m_targetBoundingBox.height() + m_targetBoundingBox.y(),
point.z() * sqrtf(m_targetBoundingBox.size().diagonalLengthSquared() / 2));
}
PassRefPtr<SVGFilter> SVGFilter::create(const AffineTransform& absoluteTransform, const IntRect& absoluteSourceDrawingRegion, const FloatRect& targetBoundingBox, const FloatRect& filterRegion, bool effectBBoxMode)
{
return adoptRef(new SVGFilter(absoluteTransform, absoluteSourceDrawingRegion, targetBoundingBox, filterRegion, effectBBoxMode));
......
......@@ -38,6 +38,7 @@ public:
virtual float applyHorizontalScale(float value) const OVERRIDE;
virtual float applyVerticalScale(float value) const OVERRIDE;
virtual FloatPoint3D resolve3dPoint(const FloatPoint3D&) const OVERRIDE;
virtual IntRect sourceImageRect() const OVERRIDE { return m_absoluteSourceDrawingRegion; }
FloatRect targetBoundingBox() const { return m_targetBoundingBox; }
......
......@@ -70,6 +70,7 @@ public:
{
return value * m_absoluteTransform.d();
}
virtual FloatPoint3D resolve3dPoint(const FloatPoint3D& point) const { return point; }
virtual IntRect sourceImageRect() const = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment