Skip to content
Permalink
Browse files
[Filters] LightSource should keep its points in <length-percentage> u…
…nits

https://bugs.webkit.org/show_bug.cgi?id=241535
<rdar://problem/94973414>

Reviewed by Cameron McCormack.

PointLightSource and SpotLightSource are created with points in user space coordinates.
See SVGFEPointLightElement::lightSource() and SVGFESpotLightElement::lightSource().
But this requires knowing the filter targetBoundingBox and the primitiveUnits at
the LightSource creation time.

When dynamically updating these points through SVGFEDiffuseLightingElement::
setFilterEffectAttribute() or SVGFESpecularLightingElement::setFilterEffectAttribute()
the SVGFilter is not available and these points are stored as <length-percentage>
coordinates. This means if the primitiveUnits is SVG_UNIT_TYPE_OBJECTBOUNDINGBOX,
fractions of the targetBoundingBox will be treated as lengths in user space.

The fix is to store the LightSources points in <length-percentage> units and to
resolve them to user space coordinates in initPaintingData().

* LayoutTests/svg/filters/feDiffuseLighting-feSpotLight-dynamic-update-expected.svg: Added.
* LayoutTests/svg/filters/feDiffuseLighting-feSpotLight-dynamic-update.svg: Added.
* LayoutTests/svg/filters/feSpecularLighting-fePointLight-dynamic-update-expected.svg: Added.
* LayoutTests/svg/filters/feSpecularLighting-fePointLight-dynamic-update.svg: Added.
* Source/WebCore/platform/graphics/filters/Filter.h:
(WebCore::Filter::resolvedPoint3D const):
* Source/WebCore/platform/graphics/filters/PointLightSource.cpp:
(WebCore::PointLightSource::PointLightSource):
(WebCore::PointLightSource::initPaintingData const):
(WebCore::PointLightSource::setX):
(WebCore::PointLightSource::setY):
(WebCore::PointLightSource::setZ):
* Source/WebCore/platform/graphics/filters/PointLightSource.h:
(WebCore::PointLightSource::position const):
(WebCore::PointLightSource::encode const):
* Source/WebCore/platform/graphics/filters/SpotLightSource.cpp:
(WebCore::SpotLightSource::SpotLightSource):
(WebCore::SpotLightSource::initPaintingData const):
(WebCore::SpotLightSource::setX):
(WebCore::SpotLightSource::setY):
(WebCore::SpotLightSource::setZ):
(WebCore::SpotLightSource::setPointsAtX):
(WebCore::SpotLightSource::setPointsAtY):
(WebCore::SpotLightSource::setPointsAtZ):
* Source/WebCore/platform/graphics/filters/SpotLightSource.h:
(WebCore::SpotLightSource::position const):
(WebCore::SpotLightSource::direction const):
(WebCore::SpotLightSource::encode const):
* Source/WebCore/svg/SVGFEBlendElement.cpp:
(WebCore::SVGFEBlendElement::filterEffect const):
* Source/WebCore/svg/SVGFEBlendElement.h:
* Source/WebCore/svg/SVGFEColorMatrixElement.cpp:
(WebCore::SVGFEColorMatrixElement::filterEffect const):
* Source/WebCore/svg/SVGFEColorMatrixElement.h:
* Source/WebCore/svg/SVGFEComponentTransferElement.cpp:
(WebCore::SVGFEComponentTransferElement::filterEffect const):
* Source/WebCore/svg/SVGFEComponentTransferElement.h:
* Source/WebCore/svg/SVGFECompositeElement.cpp:
(WebCore::SVGFECompositeElement::filterEffect const):
* Source/WebCore/svg/SVGFECompositeElement.h:
* Source/WebCore/svg/SVGFEConvolveMatrixElement.cpp:
(WebCore::SVGFEConvolveMatrixElement::filterEffect const):
* Source/WebCore/svg/SVGFEConvolveMatrixElement.h:
* Source/WebCore/svg/SVGFEDiffuseLightingElement.cpp:
(WebCore::SVGFEDiffuseLightingElement::filterEffect const):
* Source/WebCore/svg/SVGFEDiffuseLightingElement.h:
* Source/WebCore/svg/SVGFEDisplacementMapElement.cpp:
(WebCore::SVGFEDisplacementMapElement::filterEffect const):
* Source/WebCore/svg/SVGFEDisplacementMapElement.h:
* Source/WebCore/svg/SVGFEDistantLightElement.cpp:
(WebCore::SVGFEDistantLightElement::lightSource const):
* Source/WebCore/svg/SVGFEDistantLightElement.h:
* Source/WebCore/svg/SVGFEDropShadowElement.cpp:
(WebCore::SVGFEDropShadowElement::filterEffect const):
* Source/WebCore/svg/SVGFEDropShadowElement.h:
* Source/WebCore/svg/SVGFEFloodElement.cpp:
(WebCore::SVGFEFloodElement::filterEffect const):
* Source/WebCore/svg/SVGFEFloodElement.h:
* Source/WebCore/svg/SVGFEGaussianBlurElement.cpp:
(WebCore::SVGFEGaussianBlurElement::filterEffect const):
* Source/WebCore/svg/SVGFEGaussianBlurElement.h:
* Source/WebCore/svg/SVGFEImageElement.cpp:
(WebCore::SVGFEImageElement::filterEffect const):
* Source/WebCore/svg/SVGFEImageElement.h:
* Source/WebCore/svg/SVGFELightElement.h:
* Source/WebCore/svg/SVGFEMergeElement.cpp:
(WebCore::SVGFEMergeElement::filterEffect const):
* Source/WebCore/svg/SVGFEMergeElement.h:
* Source/WebCore/svg/SVGFEMorphologyElement.cpp:
(WebCore::SVGFEMorphologyElement::filterEffect const):
* Source/WebCore/svg/SVGFEMorphologyElement.h:
* Source/WebCore/svg/SVGFEOffsetElement.cpp:
(WebCore::SVGFEOffsetElement::filterEffect const):
* Source/WebCore/svg/SVGFEOffsetElement.h:
* Source/WebCore/svg/SVGFEPointLightElement.cpp:
(WebCore::SVGFEPointLightElement::lightSource const):
* Source/WebCore/svg/SVGFEPointLightElement.h:
* Source/WebCore/svg/SVGFESpecularLightingElement.cpp:
(WebCore::SVGFESpecularLightingElement::filterEffect const):
* Source/WebCore/svg/SVGFESpecularLightingElement.h:
* Source/WebCore/svg/SVGFESpotLightElement.cpp:
(WebCore::SVGFESpotLightElement::lightSource const):
* Source/WebCore/svg/SVGFESpotLightElement.h:
* Source/WebCore/svg/SVGFETileElement.cpp:
(WebCore::SVGFETileElement::filterEffect const):
* Source/WebCore/svg/SVGFETileElement.h:
* Source/WebCore/svg/SVGFETurbulenceElement.cpp:
(WebCore::SVGFETurbulenceElement::filterEffect const):
* Source/WebCore/svg/SVGFETurbulenceElement.h:
* Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h:
* Source/WebCore/svg/graphics/filters/SVGFilter.cpp:
(WebCore::SVGFilter::resolvedPoint3D const):
* Source/WebCore/svg/graphics/filters/SVGFilter.h:
* Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp:
(WebCore::SVGFilterBuilder::buildFilterExpression):

Canonical link: https://commits.webkit.org/251486@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@295481 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
shallawa committed Jun 13, 2022
1 parent ea891d3 commit ab59722dc517c798f7d88bfe4dcb7b33b8473e7e
Show file tree
Hide file tree
Showing 54 changed files with 210 additions and 139 deletions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -23,6 +23,7 @@

#include "FilterEffectVector.h"
#include "FilterFunction.h"
#include "FloatPoint3D.h"
#include "FloatRect.h"
#include "GraphicsTypes.h"
#include "ImageBuffer.h"
@@ -53,6 +54,7 @@ class Filter : public FilterFunction {
void setClipOperation(ClipOperation clipOperation) { m_clipOperation = clipOperation; }

virtual FloatSize resolvedSize(const FloatSize& size) const { return size; }
virtual FloatPoint3D resolvedPoint3D(const FloatPoint3D& point) const { return point; }

FloatPoint scaledByFilterScale(const FloatPoint&) const;
FloatSize scaledByFilterScale(const FloatSize&) const;
@@ -5,7 +5,7 @@
* Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org>
* Copyright (C) 2011 University of Szeged
* Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -45,17 +45,18 @@ Ref<PointLightSource> PointLightSource::create(const FloatPoint3D& position)

PointLightSource::PointLightSource(const FloatPoint3D& position)
: LightSource(LS_POINT)
, m_userSpacePosition(position)
, m_position(position)
{
}

void PointLightSource::initPaintingData(const Filter& filter, const FilterImage& result, PaintingData&) const
{
auto absolutePosition = filter.scaledByFilterScale(m_userSpacePosition.xy());
auto position = filter.resolvedPoint3D(m_position);
auto absolutePosition = filter.scaledByFilterScale(position.xy());
m_bufferPosition.setXY(result.mappedAbsolutePoint(absolutePosition));

// To scale Z, map a point offset from m_userSpacePosition in the x direction by z.
auto absoluteMappedZ = filter.scaledByFilterScale(FloatPoint { m_userSpacePosition.x() + m_userSpacePosition.z(), m_userSpacePosition.y() });
// To scale Z, map a point offset from position in the x direction by z.
auto absoluteMappedZ = filter.scaledByFilterScale(FloatPoint { position.x() + position.z(), position.y() });
m_bufferPosition.setZ(result.mappedAbsolutePoint(absoluteMappedZ).x() - m_bufferPosition.x());
}

@@ -72,25 +73,25 @@ LightSource::ComputedLightingData PointLightSource::computePixelLightingData(con

bool PointLightSource::setX(float x)
{
if (m_userSpacePosition.x() == x)
if (m_position.x() == x)
return false;
m_userSpacePosition.setX(x);
m_position.setX(x);
return true;
}

bool PointLightSource::setY(float y)
{
if (m_userSpacePosition.y() == y)
if (m_position.y() == y)
return false;
m_userSpacePosition.setY(y);
m_position.setY(y);
return true;
}

bool PointLightSource::setZ(float z)
{
if (m_userSpacePosition.z() == z)
if (m_position.z() == z)
return false;
m_userSpacePosition.setZ(z);
m_position.setZ(z);
return true;
}

@@ -3,7 +3,7 @@
* Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -32,7 +32,7 @@ class PointLightSource : public LightSource {
public:
WEBCORE_EXPORT static Ref<PointLightSource> create(const FloatPoint3D& position);

const FloatPoint3D& position() const { return m_userSpacePosition; }
const FloatPoint3D& position() const { return m_position; }
bool setX(float) override;
bool setY(float) override;
bool setZ(float) override;
@@ -48,14 +48,14 @@ class PointLightSource : public LightSource {
private:
PointLightSource(const FloatPoint3D& position);

FloatPoint3D m_userSpacePosition;
FloatPoint3D m_position;
mutable FloatPoint3D m_bufferPosition;
};

template<class Encoder>
void PointLightSource::encode(Encoder& encoder) const
{
encoder << m_userSpacePosition;
encoder << m_position;
}

template<class Decoder>
@@ -6,7 +6,7 @@
* Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org>
* Copyright (C) 2011 University of Szeged
* Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -48,25 +48,28 @@ Ref<SpotLightSource> SpotLightSource::create(const FloatPoint3D& position, const
return adoptRef(*new SpotLightSource(position, direction, specularExponent, limitingConeAngle));
}

SpotLightSource::SpotLightSource(const FloatPoint3D& position, const FloatPoint3D& direction, float specularExponent, float limitingConeAngle)
SpotLightSource::SpotLightSource(const FloatPoint3D& position, const FloatPoint3D& pointsAt, float specularExponent, float limitingConeAngle)
: LightSource(LS_SPOT)
, m_userSpacePosition(position)
, m_userSpacePointsAt(direction)
, m_position(position)
, m_pointsAt(pointsAt)
, m_specularExponent(specularExponent)
, m_limitingConeAngle(limitingConeAngle)
{
}

void SpotLightSource::initPaintingData(const Filter& filter, const FilterImage& result, PaintingData& paintingData) const
{
auto absolutePosition = filter.scaledByFilterScale(m_userSpacePosition.xy());
auto position = filter.resolvedPoint3D(m_position);
auto pointsAt = filter.resolvedPoint3D(m_pointsAt);

auto absolutePosition = filter.scaledByFilterScale(position.xy());
m_bufferPosition.setXY(result.mappedAbsolutePoint(absolutePosition));

// To scale Z, map a point offset from m_userSpacePosition in the x direction by z.
auto absoluteMappedZ = filter.scaledByFilterScale(FloatPoint { m_userSpacePosition.x() + m_userSpacePosition.z(), m_userSpacePosition.y() });
// To scale Z, map a point offset from position in the x direction by z.
auto absoluteMappedZ = filter.scaledByFilterScale(FloatPoint { position.x() + position.z(), position.y() });
m_bufferPosition.setZ(result.mappedAbsolutePoint(absoluteMappedZ).x() - m_bufferPosition.x());

paintingData.directionVector = m_userSpacePointsAt - m_userSpacePosition;
paintingData.directionVector = pointsAt - position;
paintingData.directionVector.normalize();

if (!m_limitingConeAngle) {
@@ -135,49 +138,49 @@ LightSource::ComputedLightingData SpotLightSource::computePixelLightingData(cons

bool SpotLightSource::setX(float x)
{
if (m_userSpacePosition.x() == x)
if (m_position.x() == x)
return false;
m_userSpacePosition.setX(x);
m_position.setX(x);
return true;
}

bool SpotLightSource::setY(float y)
{
if (m_userSpacePosition.y() == y)
if (m_position.y() == y)
return false;
m_userSpacePosition.setY(y);
m_position.setY(y);
return true;
}

bool SpotLightSource::setZ(float z)
{
if (m_userSpacePosition.z() == z)
if (m_position.z() == z)
return false;
m_userSpacePosition.setZ(z);
m_position.setZ(z);
return true;
}

bool SpotLightSource::setPointsAtX(float pointsAtX)
{
if (m_userSpacePointsAt.x() == pointsAtX)
if (m_pointsAt.x() == pointsAtX)
return false;
m_userSpacePointsAt.setX(pointsAtX);
m_pointsAt.setX(pointsAtX);
return true;
}

bool SpotLightSource::setPointsAtY(float pointsAtY)
{
if (m_userSpacePointsAt.y() == pointsAtY)
if (m_pointsAt.y() == pointsAtY)
return false;
m_userSpacePointsAt.setY(pointsAtY);
m_pointsAt.setY(pointsAtY);
return true;
}

bool SpotLightSource::setPointsAtZ(float pointsAtZ)
{
if (m_userSpacePointsAt.z() == pointsAtZ)
if (m_pointsAt.z() == pointsAtZ)
return false;
m_userSpacePointsAt.setZ(pointsAtZ);
m_pointsAt.setZ(pointsAtZ);
return true;
}

@@ -3,7 +3,7 @@
* Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
* Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
* Copyright (C) 2005 Eric Seidel <eric@webkit.org>
* Copyright (C) 2021 Apple Inc. All rights reserved.
* Copyright (C) 2021-2022 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -30,10 +30,10 @@ namespace WebCore {

class SpotLightSource : public LightSource {
public:
WEBCORE_EXPORT static Ref<SpotLightSource> create(const FloatPoint3D& position, const FloatPoint3D& direction, float specularExponent, float limitingConeAngle);
WEBCORE_EXPORT static Ref<SpotLightSource> create(const FloatPoint3D& position, const FloatPoint3D& pointsAt, float specularExponent, float limitingConeAngle);

const FloatPoint3D& position() const { return m_userSpacePosition; }
const FloatPoint3D& direction() const { return m_userSpacePointsAt; }
const FloatPoint3D& position() const { return m_position; }
const FloatPoint3D& direction() const { return m_pointsAt; }
float specularExponent() const { return m_specularExponent; }
float limitingConeAngle() const { return m_limitingConeAngle; }

@@ -58,8 +58,8 @@ class SpotLightSource : public LightSource {
private:
SpotLightSource(const FloatPoint3D& position, const FloatPoint3D& direction, float specularExponent, float limitingConeAngle);

FloatPoint3D m_userSpacePosition;
FloatPoint3D m_userSpacePointsAt;
FloatPoint3D m_position;
FloatPoint3D m_pointsAt;

mutable FloatPoint3D m_bufferPosition;

@@ -70,8 +70,8 @@ class SpotLightSource : public LightSource {
template<class Encoder>
void SpotLightSource::encode(Encoder& encoder) const
{
encoder << m_userSpacePosition;
encoder << m_userSpacePointsAt;
encoder << m_position;
encoder << m_pointsAt;
encoder << m_specularExponent;
encoder << m_limitingConeAngle;
}
@@ -97,7 +97,7 @@ void SVGFEBlendElement::svgAttributeChanged(const QualifiedName& attrName)
SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
}

RefPtr<FilterEffect> SVGFEBlendElement::filterEffect(const SVGFilter&, const FilterEffectVector&, const GraphicsContext&) const
RefPtr<FilterEffect> SVGFEBlendElement::filterEffect(const FilterEffectVector&, const GraphicsContext&) const
{
return FEBlend::create(mode());
}
@@ -71,7 +71,7 @@ class SVGFEBlendElement final : public SVGFilterPrimitiveStandardAttributes {

bool setFilterEffectAttribute(FilterEffect*, const QualifiedName& attrName) override;
Vector<AtomString> filterEffectInputsNames() const override { return { AtomString { in1() }, AtomString { in2() } }; }
RefPtr<FilterEffect> filterEffect(const SVGFilter&, const FilterEffectVector&, const GraphicsContext& destinationContext) const override;
RefPtr<FilterEffect> filterEffect(const FilterEffectVector&, const GraphicsContext& destinationContext) const override;

PropertyRegistry m_propertyRegistry { *this };
Ref<SVGAnimatedString> m_in1 { SVGAnimatedString::create(this) };
@@ -98,7 +98,7 @@ void SVGFEColorMatrixElement::svgAttributeChanged(const QualifiedName& attrName)
SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
}

RefPtr<FilterEffect> SVGFEColorMatrixElement::filterEffect(const SVGFilter&, const FilterEffectVector&, const GraphicsContext&) const
RefPtr<FilterEffect> SVGFEColorMatrixElement::filterEffect(const FilterEffectVector&, const GraphicsContext&) const
{
Vector<float> filterValues;
ColorMatrixType filterType = type();
@@ -87,7 +87,7 @@ class SVGFEColorMatrixElement final : public SVGFilterPrimitiveStandardAttribute

bool setFilterEffectAttribute(FilterEffect*, const QualifiedName&) override;
Vector<AtomString> filterEffectInputsNames() const override { return { AtomString { in1() } }; }
RefPtr<FilterEffect> filterEffect(const SVGFilter&, const FilterEffectVector&, const GraphicsContext& destinationContext) const override;
RefPtr<FilterEffect> filterEffect(const FilterEffectVector&, const GraphicsContext& destinationContext) const override;

PropertyRegistry m_propertyRegistry { *this };
Ref<SVGAnimatedString> m_in1 { SVGAnimatedString::create(this) };
@@ -62,7 +62,7 @@ void SVGFEComponentTransferElement::parseAttribute(const QualifiedName& name, co
SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value);
}

RefPtr<FilterEffect> SVGFEComponentTransferElement::filterEffect(const SVGFilter&, const FilterEffectVector&, const GraphicsContext&) const
RefPtr<FilterEffect> SVGFEComponentTransferElement::filterEffect(const FilterEffectVector&, const GraphicsContext&) const
{
ComponentTransferFunction red;
ComponentTransferFunction green;

0 comments on commit ab59722

Please sign in to comment.