2 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
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.
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.
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.
21 #include "RenderSVGResourceContainer.h"
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>
32 static inline SVGDocumentExtensions& svgExtensionsFromElement(SVGElement& element)
34 return element.document().accessSVGExtensions();
37 RenderSVGResourceContainer::RenderSVGResourceContainer(SVGElement& element, PassRef<RenderStyle> style)
38 : RenderSVGHiddenContainer(element, WTF::move(style))
39 , m_id(element.getIdAttribute())
41 , m_isInvalidating(false)
45 RenderSVGResourceContainer::~RenderSVGResourceContainer()
48 svgExtensionsFromElement(element()).removeResource(m_id);
51 void RenderSVGResourceContainer::layout()
53 StackStats::LayoutCheckPoint layoutCheckPoint;
54 // Invalidate all resources if our layout changed.
55 if (everHadLayout() && selfNeedsLayout())
56 RenderSVGRoot::addResourceForClientInvalidation(this);
58 RenderSVGHiddenContainer::layout();
61 void RenderSVGResourceContainer::willBeDestroyed()
63 SVGResourcesCache::resourceDestroyed(*this);
64 RenderSVGHiddenContainer::willBeDestroyed();
67 void RenderSVGResourceContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
69 RenderSVGHiddenContainer::styleDidChange(diff, oldStyle);
77 void RenderSVGResourceContainer::idChanged()
79 // Invalidate all our current clients.
80 removeAllClientsFromCache();
82 // Remove old id, that is guaranteed to be present in cache.
83 svgExtensionsFromElement(element()).removeResource(m_id);
84 m_id = element().getIdAttribute();
89 void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode mode)
91 if ((m_clients.isEmpty() && m_clientLayers.isEmpty()) || m_isInvalidating)
94 m_isInvalidating = true;
95 bool needsLayout = mode == LayoutAndBoundariesInvalidation;
96 bool markForInvalidation = mode != ParentOnlyInvalidation;
98 for (auto* client : m_clients) {
99 if (client->isSVGResourceContainer()) {
100 toRenderSVGResourceContainer(*client).removeAllClientsFromCache(markForInvalidation);
104 if (markForInvalidation)
105 markClientForInvalidation(*client, mode);
107 RenderSVGResource::markForLayoutAndParentResourceInvalidation(*client, needsLayout);
110 markAllClientLayersForInvalidation();
112 m_isInvalidating = false;
115 void RenderSVGResourceContainer::markAllClientLayersForInvalidation()
117 for (auto* clientLayer : m_clientLayers)
118 clientLayer->filterNeedsRepaint();
121 void RenderSVGResourceContainer::markClientForInvalidation(RenderObject& client, InvalidationMode mode)
123 ASSERT(!m_clients.isEmpty());
126 case LayoutAndBoundariesInvalidation:
127 case BoundariesInvalidation:
128 client.setNeedsBoundariesUpdate();
130 case RepaintInvalidation:
131 if (!client.documentBeingDestroyed())
134 case ParentOnlyInvalidation:
139 void RenderSVGResourceContainer::addClient(RenderElement& client)
141 m_clients.add(&client);
144 void RenderSVGResourceContainer::removeClient(RenderElement& client)
146 removeClientFromCache(client, false);
147 m_clients.remove(&client);
150 void RenderSVGResourceContainer::addClientRenderLayer(RenderLayer* client)
153 m_clientLayers.add(client);
156 void RenderSVGResourceContainer::removeClientRenderLayer(RenderLayer* client)
159 m_clientLayers.remove(client);
162 void RenderSVGResourceContainer::registerResource()
164 SVGDocumentExtensions& extensions = svgExtensionsFromElement(element());
165 if (!extensions.isIdOfPendingResource(m_id)) {
166 extensions.addResource(m_id, this);
170 std::unique_ptr<SVGDocumentExtensions::PendingElements> clients = extensions.removePendingResource(m_id);
172 // Cache us with the new id.
173 extensions.addResource(m_id, this);
175 // Update cached resources of pending clients.
176 for (auto* client : *clients) {
177 ASSERT(client->hasPendingResources());
178 extensions.clearHasPendingResourcesIfPossible(client);
179 auto* renderer = client->renderer();
182 SVGResourcesCache::clientStyleChanged(*renderer, StyleDifferenceLayout, renderer->style());
183 renderer->setNeedsLayout();
187 bool RenderSVGResourceContainer::shouldTransformOnTextPainting(const RenderElement& renderer, AffineTransform& resourceTransform)
190 UNUSED_PARAM(renderer);
191 UNUSED_PARAM(resourceTransform);
194 // This method should only be called for RenderObjects that deal with text rendering. Cmp. RenderObject.h's is*() methods.
195 ASSERT(renderer.isSVGText() || renderer.isSVGTextPath() || renderer.isSVGInline());
197 // In text drawing, the scaling part of the graphics context CTM is removed, compare SVGInlineTextBox::paintTextWithShadows.
198 // So, we use that scaling factor here, too, and then push it down to pattern or gradient space
199 // in order to keep the pattern or gradient correctly scaled.
200 float scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(renderer);
201 if (scalingFactor == 1)
203 resourceTransform.scale(scalingFactor);
208 // FIXME: This does not belong here.
209 AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform)
211 if (!object->isSVGShape())
212 return resourceTransform;
214 SVGGraphicsElement* element = toSVGGraphicsElement(object->node());
215 AffineTransform transform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
216 transform *= resourceTransform;