[GTK4] WTR crash in PlatformWebView::dismissAllPopupMenus()
[WebKit-https.git] / Source / WebCore / svg / graphics / filters / SVGFEImage.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
4  * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
5  * Copyright (C) 2010 Dirk Schulze <krit@webkit.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24 #include "SVGFEImage.h"
25
26 #include "AffineTransform.h"
27 #include "Filter.h"
28 #include "GraphicsContext.h"
29 #include "RenderElement.h"
30 #include "RenderTreeAsText.h"
31 #include "SVGElement.h"
32 #include "SVGRenderingContext.h"
33 #include "SVGURIReference.h"
34 #include <wtf/text/TextStream.h>
35
36 namespace WebCore {
37
38 FEImage::FEImage(Filter& filter, RefPtr<Image> image, const SVGPreserveAspectRatioValue& preserveAspectRatio)
39     : FilterEffect(filter, Type::Image)
40     , m_image(image)
41     , m_preserveAspectRatio(preserveAspectRatio)
42 {
43 }
44
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
63 void FEImage::determineAbsolutePaintRect()
64 {
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());
72
73     if (clipsToBounds())
74         paintRect.intersect(maxEffectRect());
75     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();
88 }
89
90 void FEImage::platformApplySoftware()
91 {
92     RenderElement* renderer = referencedRenderer();
93     if (!m_image && !renderer)
94         return;
95
96     // FEImage results are always in DestinationColorSpace::SRGB
97     setResultColorSpace(DestinationColorSpace::SRGB);
98
99     ImageBuffer* resultImage = createImageBufferResult();
100     if (!resultImage)
101         return;
102
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
116     auto& context = resultImage->context();
117
118     if (renderer) {
119         const AffineTransform& absoluteTransform = filter().absoluteTransform();
120         context.concatCTM(absoluteTransform);
121
122         auto contextNode = makeRefPtr(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));
131         }
132
133         AffineTransform contentTransformation;
134         SVGRenderingContext::renderSubtreeToContext(context, *renderer, contentTransformation);
135         return;
136     }
137
138     context.drawImage(*m_image, destRect, srcRect);
139 }
140
141 TextStream& FEImage::externalRepresentation(TextStream& ts, RepresentationType representation) const
142 {
143     FloatSize imageSize;
144     if (m_image)
145         imageSize = m_image->size();
146     else if (RenderObject* renderer = referencedRenderer())
147         imageSize = enclosingIntRect(renderer->repaintRectInLocalCoordinates()).size();
148     ts << indent << "[feImage";
149     FilterEffect::externalRepresentation(ts, representation);
150     ts << " image-size=\"" << imageSize.width() << "x" << imageSize.height() << "\"]\n";
151     // FIXME: should this dump also object returned by SVGFEImage::image() ?
152     return ts;
153 }
154
155 } // namespace WebCore