Remove unnecessary #include SVGResourcesCache.h in SVGDocumentExtensions.h; use forwa...
[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
22 #if ENABLE(SVG)
23 #include "RenderSVGResourceContainer.h"
24
25 #include "RenderSVGShadowTreeRootContainer.h"
26 #include "SVGResourcesCache.h"
27 #include "SVGStyledTransformableElement.h"
28
29 namespace WebCore {
30
31 static inline SVGDocumentExtensions* svgExtensionsFromNode(Node* node)
32 {
33     ASSERT(node);
34     ASSERT(node->document());
35     return node->document()->accessSVGExtensions();
36 }
37
38 RenderSVGResourceContainer::RenderSVGResourceContainer(SVGStyledElement* node)
39     : RenderSVGHiddenContainer(node)
40     , m_id(node->hasID() ? node->getIdAttribute() : nullAtom)
41     , m_registered(false)
42     , m_isInvalidating(false)
43 {
44 }
45
46 RenderSVGResourceContainer::~RenderSVGResourceContainer()
47 {
48     if (m_registered)
49         svgExtensionsFromNode(node())->removeResource(m_id);
50 }
51
52 void RenderSVGResourceContainer::layout()
53 {
54     // Invalidate all resources if our layout changed.
55     if (m_everHadLayout && selfNeedsLayout())
56         removeAllClientsFromCache();
57
58     RenderSVGHiddenContainer::layout();
59 }
60
61 void RenderSVGResourceContainer::willBeDestroyed()
62 {
63     SVGResourcesCache::resourceDestroyed(this);
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     SVGDocumentExtensions* extensions = svgExtensionsFromNode(node());
84     extensions->removeResource(m_id);
85     m_id = static_cast<Element*>(node())->getIdAttribute();
86
87     registerResource();
88 }
89
90 void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode mode)
91 {
92     if (m_clients.isEmpty() || m_isInvalidating)
93         return;
94
95     m_isInvalidating = true;
96     bool needsLayout = mode == LayoutAndBoundariesInvalidation;
97     bool markForInvalidation = mode != ParentOnlyInvalidation;
98
99     HashSet<RenderObject*>::iterator end = m_clients.end();
100     for (HashSet<RenderObject*>::iterator it = m_clients.begin(); it != end; ++it) {
101         RenderObject* client = *it;
102         if (client->isSVGResourceContainer()) {
103             client->toRenderSVGResourceContainer()->removeAllClientsFromCache(markForInvalidation);
104             continue;
105         }
106
107         if (markForInvalidation)
108             markClientForInvalidation(client, mode);
109
110         if (needsLayout)
111             client->setNeedsLayout(true);
112
113         // Invalidate resources in ancestor chain, if needed.
114         RenderObject* current = client->parent();
115         while (current) {
116             if (current->isSVGResourceContainer()) {
117                 current->toRenderSVGResourceContainer()->removeAllClientsFromCache(markForInvalidation);
118                 break;
119             }
120
121             current = current->parent();
122         }
123     }
124     m_isInvalidating = false;
125 }
126
127 void RenderSVGResourceContainer::markClientForInvalidation(RenderObject* client, InvalidationMode mode)
128 {
129     ASSERT(client);
130     ASSERT(!m_clients.isEmpty());
131
132     switch (mode) {
133     case LayoutAndBoundariesInvalidation:
134     case BoundariesInvalidation:
135         client->setNeedsBoundariesUpdate();
136         break;
137     case RepaintInvalidation:
138         if (client->view())
139             client->repaint();
140         break;
141     case ParentOnlyInvalidation:
142         break;
143     }
144 }
145
146 void RenderSVGResourceContainer::addClient(RenderObject* client)
147 {
148     ASSERT(client);
149     m_clients.add(client);
150 }
151
152 void RenderSVGResourceContainer::removeClient(RenderObject* client)
153 {
154     ASSERT(client);
155     m_clients.remove(client);
156 }
157
158 void RenderSVGResourceContainer::registerResource()
159 {
160     SVGDocumentExtensions* extensions = svgExtensionsFromNode(node());
161     if (!extensions->hasPendingResources(m_id)) {
162         extensions->addResource(m_id, this);
163         return;
164     }
165
166     OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions->removePendingResource(m_id));
167
168     // Cache us with the new id.
169     extensions->addResource(m_id, this);
170
171     // Update cached resources of pending clients.
172     const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end();
173     for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) {
174         ASSERT((*it)->hasPendingResources());
175         (*it)->clearHasPendingResourcesIfPossible();
176         RenderObject* renderer = (*it)->renderer();
177         if (!renderer)
178             continue;
179         SVGResourcesCache::clientUpdatedFromElement(renderer, renderer->style());
180         renderer->setNeedsLayout(true);
181     }
182 }
183
184 // FIXME: This does not belong here.
185 AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform)
186 {
187     if (!object->isSVGPath())
188         return resourceTransform;
189
190     SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node());
191     AffineTransform transform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
192     transform *= resourceTransform;
193     return transform;
194 }
195
196 }
197
198 #endif