Use "= default" to denote default constructor or destructor
[WebKit-https.git] / Source / WebCore / rendering / svg / RenderSVGResourceContainer.cpp
1 /*
2  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "RenderSVGResourceContainer.h"
22
23 #include "RenderLayer.h"
24 #include "RenderSVGRoot.h"
25 #include "RenderView.h"
26 #include "SVGRenderingContext.h"
27 #include "SVGResourcesCache.h"
28 #include <wtf/StackStats.h>
29
30 namespace WebCore {
31
32 static inline SVGDocumentExtensions& svgExtensionsFromElement(SVGElement& element)
33 {
34     return element.document().accessSVGExtensions();
35 }
36
37 RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement& element, RenderStyle&& style)
38     : RenderSVGHiddenContainer(element, WTFMove(style))
39     , m_id(element.getIdAttribute())
40 {
41 }
42
43 RenderSVGResourceContainer::~RenderSVGResourceContainer() = default;
44
45 void RenderSVGResourceContainer::layout()
46 {
47     StackStats::LayoutCheckPoint layoutCheckPoint;
48     // Invalidate all resources if our layout changed.
49     if (selfNeedsClientInvalidation())
50         RenderSVGRoot::addResourceForClientInvalidation(this);
51
52     RenderSVGHiddenContainer::layout();
53 }
54
55 void RenderSVGResourceContainer::willBeDestroyed()
56 {
57     SVGResourcesCache::resourceDestroyed(*this);
58
59     if (m_registered) {
60         svgExtensionsFromElement(element()).removeResource(m_id);
61         m_registered = false;
62     }
63
64     RenderSVGHiddenContainer::willBeDestroyed();
65 }
66
67 void RenderSVGResourceContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
68 {
69     RenderSVGHiddenContainer::styleDidChange(diff, oldStyle);
70
71     if (!m_registered) {
72         m_registered = true;
73         registerResource();
74     }
75 }
76
77 void RenderSVGResourceContainer::idChanged()
78 {
79     // Invalidate all our current clients.
80     removeAllClientsFromCache();
81
82     // Remove old id, that is guaranteed to be present in cache.
83     svgExtensionsFromElement(element()).removeResource(m_id);
84     m_id = element().getIdAttribute();
85
86     registerResource();
87 }
88
89 void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode mode)
90 {
91     if ((m_clients.isEmpty() && m_clientLayers.isEmpty()) || m_isInvalidating)
92         return;
93
94     m_isInvalidating = true;
95     bool needsLayout = mode == LayoutAndBoundariesInvalidation;
96     bool markForInvalidation = mode != ParentOnlyInvalidation;
97     auto* root = SVGRenderSupport::findTreeRootObject(*this);
98
99     for (auto* client : m_clients) {
100         // We should not mark any client outside the current root for invalidation
101         if (root != SVGRenderSupport::findTreeRootObject(*client))
102             continue;
103
104         if (is<RenderSVGResourceContainer>(*client)) {
105             downcast<RenderSVGResourceContainer>(*client).removeAllClientsFromCache(markForInvalidation);
106             continue;
107         }
108
109         if (markForInvalidation)
110             markClientForInvalidation(*client, mode);
111
112         RenderSVGResource::markForLayoutAndParentResourceInvalidation(*client, needsLayout);
113     }
114
115     markAllClientLayersForInvalidation();
116
117     m_isInvalidating = false;
118 }
119
120 void RenderSVGResourceContainer::markAllClientLayersForInvalidation()
121 {
122     for (auto* clientLayer : m_clientLayers)
123         clientLayer->filterNeedsRepaint();
124 }
125
126 void RenderSVGResourceContainer::markClientForInvalidation(RenderObject& client, InvalidationMode mode)
127 {
128     ASSERT(!m_clients.isEmpty());
129
130     switch (mode) {
131     case LayoutAndBoundariesInvalidation:
132     case BoundariesInvalidation:
133         client.setNeedsBoundariesUpdate();
134         break;
135     case RepaintInvalidation:
136         if (!client.renderTreeBeingDestroyed())
137             client.repaint();
138         break;
139     case ParentOnlyInvalidation:
140         break;
141     }
142 }
143
144 void RenderSVGResourceContainer::addClient(RenderElement& client)
145 {
146     m_clients.add(&client);
147 }
148
149 void RenderSVGResourceContainer::removeClient(RenderElement& client)
150 {
151     removeClientFromCache(client, false);
152     m_clients.remove(&client);
153 }
154
155 void RenderSVGResourceContainer::addClientRenderLayer(RenderLayer* client)
156 {
157     ASSERT(client);
158     m_clientLayers.add(client);
159 }
160
161 void RenderSVGResourceContainer::removeClientRenderLayer(RenderLayer* client)
162 {
163     ASSERT(client);
164     m_clientLayers.remove(client);
165 }
166
167 void RenderSVGResourceContainer::registerResource()
168 {
169     SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
170     if (!extensions.isIdOfPendingResource(m_id)) {
171         extensions.addResource(m_id, this);
172         return;
173     }
174
175     std::unique_ptr<SVGDocumentExtensions::PendingElements> clients = extensions.removePendingResource(m_id);
176
177     // Cache us with the new id.
178     extensions.addResource(m_id, this);
179
180     // Update cached resources of pending clients.
181     for (auto* client : *clients) {
182         ASSERT(client->hasPendingResources());
183         extensions.clearHasPendingResourcesIfPossible(client);
184         auto* renderer = client->renderer();
185         if (!renderer)
186             continue;
187         SVGResourcesCache::clientStyleChanged(*renderer, StyleDifferenceLayout, renderer->style());
188         renderer->setNeedsLayout();
189     }
190 }
191
192 bool RenderSVGResourceContainer::shouldTransformOnTextPainting(const RenderElement& renderer, AffineTransform& resourceTransform)
193 {
194 #if USE(CG)
195     UNUSED_PARAM(renderer);
196     UNUSED_PARAM(resourceTransform);
197     return false;
198 #else
199     // This method should only be called for RenderObjects that deal with text rendering. Cmp. RenderObject.h's is*() methods.
200     ASSERT(renderer.isSVGText() || renderer.isSVGTextPath() || renderer.isSVGInline());
201
202     // In text drawing, the scaling part of the graphics context CTM is removed, compare SVGInlineTextBox::paintTextWithShadows.
203     // So, we use that scaling factor here, too, and then push it down to pattern or gradient space
204     // in order to keep the pattern or gradient correctly scaled.
205     float scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(renderer);
206     if (scalingFactor == 1)
207         return false;
208     resourceTransform.scale(scalingFactor);
209     return true;
210 #endif
211 }
212
213 // FIXME: This does not belong here.
214 AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform)
215 {
216     if (!object->isSVGShape())
217         return resourceTransform;
218
219     SVGGraphicsElement* element = downcast<SVGGraphicsElement>(object->node());
220     AffineTransform transform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
221     transform *= resourceTransform;
222     return transform;
223 }
224
225 }