⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 285481 in webkit


Ignore:
Timestamp:
Nov 8, 2021, 11:39:20 PM (5 years ago)
Author:
Said Abou-Hallawa
Message:

[GPU Process] Remove non-platform code form the FEImage class
https://bugs.webkit.org/show_bug.cgi?id=232369
rdar://84966765

Reviewed by Simon Fraser.

Source/WebCore:

SVGFEImageElement should create the FEImage with either an Image or an
ImageBuffer based on whether the 'href' attribute points to a resource
image or an SVG element. For the SVG element, an ImageBuffer will be
created and the renderer of this element will be drawn to it.

Instead of holding a TreeScope and Image, FEImage can hold a variant of
Image and ImageBuffer.

Tests: svg/filters/feImage-element-primitive-subregion-expected.svg

svg/filters/feImage-element-primitive-subregion.svg
svg/filters/feImage-image-primitive-subregion-expected.svg
svg/filters/feImage-image-primitive-subregion.svg

  • svg/SVGFEImageElement.cpp:

(WebCore::SVGFEImageElement::imageBufferForEffect const):
(WebCore::SVGFEImageElement::build const):

  • svg/SVGFEImageElement.h:
  • svg/graphics/filters/SVGFEImage.cpp:

(WebCore::FEImage::create):
(WebCore::FEImage::FEImage):
(WebCore::FEImage::determineAbsolutePaintRect):
(WebCore::FEImage::platformApplySoftware):
(WebCore::FEImage::externalRepresentation const):
(WebCore::FEImage::createWithImage): Deleted.
(WebCore::FEImage::createWithIRIReference): Deleted.
(WebCore::FEImage::referencedRenderer const): Deleted.

  • svg/graphics/filters/SVGFEImage.h:

LayoutTests:

  • fast/shadow-dom/svg-feimage-href-in-shadow-tree.html:

The default primitive subregion of <feImage> is { -10%, -10%, 120%, 120% }
of the bounding box. So the filter result will be shifted (-10, -10) of
this test case if we do not specify the 'x' and then 'y' attributes.
Unlike the Image based feImage, the default behavior is to display the
ImageBuffer of the element with its logical size otherwise the drawing
will be pixelated if we try to fill the whole primitive subregion. To
make this test page matches its expected page, we need to specify the 'x'
and the 'y' attributes of the <feImage> to be zeros.

With and without specifying the 'x' and the 'y' attributes, the drawing
with this patch matches the drawing of this test page in other browsers.

  • svg/filters/feImage-change-target-id-expected.txt:
  • svg/filters/feImage-element-primitive-subregion-expected.svg: Added.
  • svg/filters/feImage-element-primitive-subregion.svg: Added.
  • svg/filters/feImage-image-primitive-subregion-expected.svg: Added.
  • svg/filters/feImage-image-primitive-subregion.svg: Added.
  • svg/filters/feImage-remove-target-expected.txt:
Location:
trunk
Files:
4 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r285478 r285481  
     12021-11-08  Said Abou-Hallawa  <said@apple.com>
     2
     3        [GPU Process] Remove non-platform code form the FEImage class
     4        https://bugs.webkit.org/show_bug.cgi?id=232369
     5        rdar://84966765
     6
     7        Reviewed by Simon Fraser.
     8
     9        * fast/shadow-dom/svg-feimage-href-in-shadow-tree.html:
     10        The default primitive subregion of <feImage> is { -10%, -10%, 120%, 120% }
     11        of the bounding box. So the filter result will be shifted (-10, -10) of
     12        this test case if we do not specify the 'x' and then 'y' attributes.
     13        Unlike the Image based feImage, the default behavior is to display the
     14        ImageBuffer of the element with its logical size otherwise the drawing
     15        will be pixelated if we try to fill the whole primitive subregion. To
     16        make this test page matches its expected page, we need to specify the 'x'
     17        and the 'y' attributes of the <feImage> to be zeros.
     18
     19        With and without specifying the 'x' and the 'y' attributes, the drawing
     20        with this patch matches the drawing of this test page in other browsers.
     21
     22        * svg/filters/feImage-change-target-id-expected.txt:
     23        * svg/filters/feImage-element-primitive-subregion-expected.svg: Added.
     24        * svg/filters/feImage-element-primitive-subregion.svg: Added.
     25        * svg/filters/feImage-image-primitive-subregion-expected.svg: Added.
     26        * svg/filters/feImage-image-primitive-subregion.svg: Added.
     27        * svg/filters/feImage-remove-target-expected.txt:
     28
    1292021-11-08  Patrick Griffis  <pgriffis@igalia.com>
    230
  • trunk/LayoutTests/fast/shadow-dom/svg-feimage-href-in-shadow-tree.html

    r238524 r285481  
    1414            <rect id="rect" width="100" height="100" fill="green" />
    1515            <filter id="image">
    16                 <feImage href="#rect" />
     16                <feImage x="0" y="0" href="#rect" />
    1717            </filter>
    1818        </defs>
  • trunk/LayoutTests/svg/filters/feImage-change-target-id-expected.txt

    r166582 r285481  
    66      RenderSVGRect {rect} at (0,0) size 100x100 [fill={[type=SOLID] [color=#008000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
    77      RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
    8         [feImage image-size="0.00x0.00"]
    98    RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
    109      [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
  • trunk/LayoutTests/svg/filters/feImage-remove-target-expected.txt

    r166582 r285481  
    55    RenderSVGHiddenContainer {defs} at (0,0) size 0x0
    66      RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
    7         [feImage image-size="0.00x0.00"]
    87    RenderSVGRect {rect} at (0,0) size 111x111 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=100.00] [height=100.00]
    98      [filter="filter"] RenderSVGResourceFilter {filter} at (-10,-10) size 120x120
  • trunk/Source/WebCore/ChangeLog

    r285478 r285481  
     12021-11-08  Said Abou-Hallawa  <said@apple.com>
     2
     3        [GPU Process] Remove non-platform code form the FEImage class
     4        https://bugs.webkit.org/show_bug.cgi?id=232369
     5        rdar://84966765
     6
     7        Reviewed by Simon Fraser.
     8
     9        SVGFEImageElement should create the FEImage with either an Image or an
     10        ImageBuffer based on whether the 'href' attribute points to a resource
     11        image or an SVG element. For the SVG element, an ImageBuffer will be
     12        created and the renderer of this element will be drawn to it.
     13
     14        Instead of holding a TreeScope and Image, FEImage can hold a variant of
     15        Image and ImageBuffer.
     16
     17        Tests: svg/filters/feImage-element-primitive-subregion-expected.svg
     18               svg/filters/feImage-element-primitive-subregion.svg
     19               svg/filters/feImage-image-primitive-subregion-expected.svg
     20               svg/filters/feImage-image-primitive-subregion.svg
     21
     22        * svg/SVGFEImageElement.cpp:
     23        (WebCore::SVGFEImageElement::imageBufferForEffect const):
     24        (WebCore::SVGFEImageElement::build const):
     25        * svg/SVGFEImageElement.h:
     26        * svg/graphics/filters/SVGFEImage.cpp:
     27        (WebCore::FEImage::create):
     28        (WebCore::FEImage::FEImage):
     29        (WebCore::FEImage::determineAbsolutePaintRect):
     30        (WebCore::FEImage::platformApplySoftware):
     31        (WebCore::FEImage::externalRepresentation const):
     32        (WebCore::FEImage::createWithImage): Deleted.
     33        (WebCore::FEImage::createWithIRIReference): Deleted.
     34        (WebCore::FEImage::referencedRenderer const): Deleted.
     35        * svg/graphics/filters/SVGFEImage.h:
     36
    1372021-11-08  Patrick Griffis  <pgriffis@igalia.com>
    238
  • trunk/Source/WebCore/svg/SVGFEImageElement.cpp

    r285186 r285481  
    33 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
    44 * Copyright (C) 2010 Dirk Schulze <krit@webkit.org>
    5  * Copyright (C) 2018 Apple Inc. All rights reserved.
     5 * Copyright (C) 2018-2021 Apple Inc. All rights reserved.
    66 *
    77 * This library is free software; you can redistribute it and/or
     
    3434#include "SVGNames.h"
    3535#include "SVGPreserveAspectRatioValue.h"
     36#include "SVGRenderingContext.h"
    3637#include <wtf/IsoMallocInlines.h>
    3738
     
    176177}
    177178
     179std::tuple<RefPtr<ImageBuffer>, FloatRect> SVGFEImageElement::imageBufferForEffect() const
     180{
     181    auto target = SVGURIReference::targetElementFromIRIString(href(), treeScope());
     182    if (!is<SVGElement>(target.element))
     183        return { };
     184
     185    if (isDescendantOrShadowDescendantOf(target.element.get()))
     186        return { };
     187
     188    auto contextNode = static_pointer_cast<SVGElement>(target.element);
     189    auto renderer = contextNode->renderer();
     190    if (!renderer)
     191        return { };
     192
     193    auto absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*renderer);
     194    if (!absoluteTransform.isInvertible())
     195        return { };
     196
     197    auto shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), 0, 0);
     198
     199    auto imageRect = renderer->repaintRectInLocalCoordinates();
     200
     201    auto imageBuffer = SVGRenderingContext::createImageBuffer(imageRect, shearFreeAbsoluteTransform, DestinationColorSpace::SRGB(), RenderingMode::Unaccelerated);
     202    if (!imageBuffer)
     203        return { };
     204
     205    auto& context = imageBuffer->context();
     206    SVGRenderingContext::renderSubtreeToContext(context, *renderer, AffineTransform());
     207
     208    return { imageBuffer, imageRect };
     209}
     210
    178211RefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*, Filter& filter) const
    179212{
    180213    if (m_cachedImage)
    181         return FEImage::createWithImage(filter, m_cachedImage->imageForRenderer(renderer()), preserveAspectRatio());
    182 
    183     auto target = SVGURIReference::targetElementFromIRIString(href(), treeScope());
    184     if (isDescendantOrShadowDescendantOf(target.element.get()))
     214        return FEImage::create(filter, Ref<Image> { *m_cachedImage->imageForRenderer(renderer()) }, preserveAspectRatio());
     215
     216    auto [imageBuffer, imageRect] = imageBufferForEffect();
     217    if (!imageBuffer)
    185218        return nullptr;
    186219
    187     return FEImage::createWithIRIReference(filter, treeScope(), href(), preserveAspectRatio());
     220    return FEImage::create(filter, imageBuffer.releaseNonNull(), imageRect, preserveAspectRatio());
    188221}
    189222
  • trunk/Source/WebCore/svg/SVGFEImageElement.h

    r261597 r285481  
    22 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
    33 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
    4  * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
     4 * Copyright (C) 2018-2021 Apple Inc. All rights reserved.
    55 *
    66 * This library is free software; you can redistribute it and/or
     
    5656    void didFinishInsertingNode() override;
    5757
     58    std::tuple<RefPtr<ImageBuffer>, FloatRect> imageBufferForEffect() const;
     59
    5860    RefPtr<FilterEffect> build(SVGFilterBuilder*, Filter&) const override;
    5961
  • trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.cpp

    r282799 r285481  
    44 * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
    55 * Copyright (C) 2010 Dirk Schulze <krit@webkit.org>
     6 * Copyright (C) 2021 Apple Inc.  All rights reserved.
    67 *
    78 * This library is free software; you can redistribute it and/or
     
    2425#include "SVGFEImage.h"
    2526
    26 #include "AffineTransform.h"
    2727#include "Filter.h"
    2828#include "GraphicsContext.h"
    29 #include "RenderElement.h"
    30 #include "RenderTreeAsText.h"
    31 #include "SVGElement.h"
    32 #include "SVGRenderingContext.h"
    33 #include "SVGURIReference.h"
    3429#include <wtf/text/TextStream.h>
    3530
    3631namespace WebCore {
    3732
    38 FEImage::FEImage(Filter& filter, RefPtr<Image> image, const SVGPreserveAspectRatioValue& preserveAspectRatio)
     33Ref<FEImage> FEImage::create(Filter& filter, Ref<Image>&& image, const SVGPreserveAspectRatioValue& preserveAspectRatio)
     34{
     35    auto imageRect = FloatRect { { }, image->size() };
     36    return create(filter, WTFMove(image), imageRect, preserveAspectRatio);
     37}
     38
     39Ref<FEImage> FEImage::create(Filter& filter, SourceImage&& sourceImage, const FloatRect& sourceImageRect, const SVGPreserveAspectRatioValue& preserveAspectRatio)
     40{
     41    return adoptRef(*new FEImage(filter, WTFMove(sourceImage), sourceImageRect, preserveAspectRatio));
     42}
     43
     44FEImage::FEImage(Filter& filter, SourceImage&& sourceImage, const FloatRect& sourceImageRect, const SVGPreserveAspectRatioValue& preserveAspectRatio)
    3945    : FilterEffect(filter, Type::Image)
    40     , m_image(image)
     46    , m_sourceImage(WTFMove(sourceImage))
     47    , m_sourceImageRect(sourceImageRect)
    4148    , m_preserveAspectRatio(preserveAspectRatio)
    4249{
    4350}
    4451
    45 FEImage::FEImage(Filter& filter, TreeScope& treeScope, const String& href, const SVGPreserveAspectRatioValue& preserveAspectRatio)
    46     : FilterEffect(filter, Type::Image)
    47     , m_treeScope(&treeScope)
    48     , m_href(href)
    49     , m_preserveAspectRatio(preserveAspectRatio)
    50 {
    51 }
    52 
    53 Ref<FEImage> FEImage::createWithImage(Filter& filter, RefPtr<Image> image, const SVGPreserveAspectRatioValue& preserveAspectRatio)
    54 {
    55     return adoptRef(*new FEImage(filter, image, preserveAspectRatio));
    56 }
    57 
    58 Ref<FEImage> FEImage::createWithIRIReference(Filter& filter, TreeScope& treeScope, const String& href, const SVGPreserveAspectRatioValue& preserveAspectRatio)
    59 {
    60     return adoptRef(*new FEImage(filter, treeScope, href, preserveAspectRatio));
    61 }
    62 
    6352void FEImage::determineAbsolutePaintRect()
    6453{
    65     FloatRect paintRect = filter().absoluteTransform().mapRect(filterPrimitiveSubregion());
    66     FloatRect srcRect;
    67     if (m_image) {
    68         srcRect.setSize(m_image->size());
    69         m_preserveAspectRatio.transformRect(paintRect, srcRect);
    70     } else if (RenderElement* renderer = referencedRenderer())
    71         srcRect = filter().absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates());
     54    auto primitiveSubregion = filterPrimitiveSubregion();
     55
     56    auto imageRect = WTF::switchOn(m_sourceImage,
     57        [&] (const Ref<Image>&) {
     58            auto imageRect = primitiveSubregion;
     59            auto srcRect = m_sourceImageRect;
     60            m_preserveAspectRatio.transformRect(imageRect, srcRect);
     61            return imageRect;
     62        },
     63        [&] (const Ref<ImageBuffer>&) {
     64            return primitiveSubregion;
     65        }
     66    );
     67
     68    imageRect = filter().absoluteTransform().mapRect(imageRect);
    7269
    7370    if (clipsToBounds())
    74         paintRect.intersect(maxEffectRect());
     71        imageRect.intersect(maxEffectRect());
    7572    else
    76         paintRect.unite(maxEffectRect());
    77     setAbsolutePaintRect(enclosingIntRect(paintRect));
    78 }
    79 
    80 RenderElement* FEImage::referencedRenderer() const
    81 {
    82     if (!m_treeScope)
    83         return nullptr;
    84     auto target = SVGURIReference::targetElementFromIRIString(m_href, *m_treeScope);
    85     if (!is<SVGElement>(target.element))
    86         return nullptr;
    87     return target.element->renderer();
     73        imageRect.unite(maxEffectRect());
     74    setAbsolutePaintRect(enclosingIntRect(imageRect));
    8875}
    8976
    9077void FEImage::platformApplySoftware()
    9178{
    92     RenderElement* renderer = referencedRenderer();
    93     if (!m_image && !renderer)
    94         return;
    95 
    9679    // FEImage results are always in DestinationColorSpace::SRGB()
    9780    setResultColorSpace(DestinationColorSpace::SRGB());
     
    10184        return;
    10285
    103     FloatRect destRect = filter().absoluteTransform().mapRect(filterPrimitiveSubregion());
    104 
    105     FloatRect srcRect;
    106     if (renderer)
    107         srcRect = filter().absoluteTransform().mapRect(renderer->repaintRectInLocalCoordinates());
    108     else {
    109         srcRect = FloatRect(FloatPoint(), m_image->size());
    110         m_preserveAspectRatio.transformRect(destRect, srcRect);
    111     }
    112 
    113     IntPoint paintLocation = absolutePaintRect().location();
    114     destRect.move(-paintLocation.x(), -paintLocation.y());
    115 
     86    auto primitiveSubregion = filterPrimitiveSubregion();
    11687    auto& context = resultImage->context();
    11788
    118     if (renderer) {
    119         const AffineTransform& absoluteTransform = filter().absoluteTransform();
    120         context.concatCTM(absoluteTransform);
    121 
    122         RefPtr contextNode = downcast<SVGElement>(renderer->element());
    123         if (contextNode->hasRelativeLengths()) {
    124             SVGLengthContext lengthContext(contextNode.get());
    125             FloatSize viewportSize;
    126 
    127             // If we're referencing an element with percentage units, eg. <rect with="30%"> those values were resolved against the viewport.
    128             // Build up a transformation that maps from the viewport space to the filter primitive subregion.
    129             if (lengthContext.determineViewport(viewportSize))
    130                 context.concatCTM(makeMapBetweenRects(FloatRect(FloatPoint(), viewportSize), destRect));
     89    WTF::switchOn(m_sourceImage,
     90        [&] (const Ref<Image>& image) {
     91            auto imageRect = primitiveSubregion;
     92            auto srcRect = m_sourceImageRect;
     93            m_preserveAspectRatio.transformRect(imageRect, srcRect);
     94            imageRect = filter().absoluteTransform().mapRect(imageRect);
     95            imageRect = drawingRegionOfInputImage(IntRect(imageRect));
     96            context.drawImage(image, imageRect, srcRect);
     97        },
     98        [&] (const Ref<ImageBuffer>& imageBuffer) {
     99            auto imageRect = primitiveSubregion;
     100            imageRect.moveBy(m_sourceImageRect.location());
     101            imageRect = filter().absoluteTransform().mapRect(imageRect);
     102            imageRect = drawingRegionOfInputImage(IntRect(imageRect));
     103            context.drawImageBuffer(imageBuffer, imageRect.location());
    131104        }
    132 
    133         AffineTransform contentTransformation;
    134         SVGRenderingContext::renderSubtreeToContext(context, *renderer, contentTransformation);
    135         return;
    136     }
    137 
    138     context.drawImage(*m_image, destRect, srcRect);
     105    );
    139106}
    140107
    141108TextStream& FEImage::externalRepresentation(TextStream& ts, RepresentationType representation) const
    142109{
    143     FloatSize imageSize;
    144     if (m_image)
    145         imageSize = m_image->size();
    146     else if (RenderObject* renderer = referencedRenderer())
    147         imageSize = enclosingIntRect(renderer->repaintRectInLocalCoordinates()).size();
    148110    ts << indent << "[feImage";
    149111    FilterEffect::externalRepresentation(ts, representation);
    150     ts << " image-size=\"" << imageSize.width() << "x" << imageSize.height() << "\"]\n";
     112    ts << " image-size=\"" << m_sourceImageRect.width() << "x" << m_sourceImageRect.height() << "\"]\n";
    151113    // FIXME: should this dump also object returned by SVGFEImage::image() ?
    152114    return ts;
  • trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h

    r243259 r285481  
    44 * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
    55 * Copyright (C) 2010 Dirk Schulze <krit@webkit.org>
     6 * Copyright (C) 2021 Apple Inc.  All rights reserved.
    67 *
    78 * This library is free software; you can redistribute it and/or
     
    2425
    2526#include "FilterEffect.h"
     27#include "RenderingResourceIdentifier.h"
    2628#include "SVGPreserveAspectRatioValue.h"
    2729
    2830namespace WebCore {
    2931
    30 class Document;
    3132class Image;
    32 class RenderElement;
    33 class TreeScope;
     33class ImageBuffer;
    3434
    3535class FEImage final : public FilterEffect {
    3636public:
    37     static Ref<FEImage> createWithImage(Filter&, RefPtr<Image>, const SVGPreserveAspectRatioValue&);
    38     static Ref<FEImage> createWithIRIReference(Filter&, TreeScope&, const String&, const SVGPreserveAspectRatioValue&);
     37    using SourceImage = std::variant<
     38        Ref<Image>,
     39        Ref<ImageBuffer>
     40    >;
     41
     42    static Ref<FEImage> create(Filter&, Ref<Image>&&, const SVGPreserveAspectRatioValue&);
     43    static Ref<FEImage> create(Filter&, SourceImage&&, const FloatRect& sourceImageRect, const SVGPreserveAspectRatioValue&);
     44
     45    SourceImage& sourceImage() { return m_sourceImage; }
     46    void setImageSource(SourceImage&& sourceImage) { m_sourceImage = WTFMove(sourceImage); }
    3947
    4048private:
    41     virtual ~FEImage() = default;
    42     FEImage(Filter&, RefPtr<Image>, const SVGPreserveAspectRatioValue&);
    43     FEImage(Filter&, TreeScope&, const String&, const SVGPreserveAspectRatioValue&);
     49    FEImage(Filter&, SourceImage&&, const FloatRect& sourceImageRect, const SVGPreserveAspectRatioValue&);
    4450
    4551    const char* filterName() const final { return "FEImage"; }
    46 
    47     FilterEffectType filterEffectType() const final { return FilterEffectTypeImage; }
    48 
    49     RenderElement* referencedRenderer() const;
    5052
    5153    void platformApplySoftware() final;
     
    5355    WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType) const final;
    5456
    55     RefPtr<Image> m_image;
    56 
    57     // m_treeScope will never be a dangling reference. See https://bugs.webkit.org/show_bug.cgi?id=99243
    58     TreeScope* m_treeScope { nullptr };
    59     String m_href;
     57    SourceImage m_sourceImage;
     58    FloatRect m_sourceImageRect;
    6059    SVGPreserveAspectRatioValue m_preserveAspectRatio;
    6160};
Note: See TracChangeset for help on using the changeset viewer.