*/
#include "config.h"
-
#include "core/rendering/svg/RenderSVGResourceContainer.h"
#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderView.h"
-#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/RenderSVGResourceClipper.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/RenderSVGResourceMasker.h"
+#include "core/rendering/svg/SVGResources.h"
#include "core/rendering/svg/SVGResourcesCache.h"
-#include "core/svg/SVGGraphicsElement.h"
#include "wtf/TemporaryChange.h"
if (markForInvalidation)
markClientForInvalidation(client, mode);
- RenderSVGResource::markForLayoutAndParentResourceInvalidation(client, needsLayout);
+ RenderSVGResourceContainer::markForLayoutAndParentResourceInvalidation(client, needsLayout);
}
markAllClientLayersForInvalidation();
client->setNeedsBoundariesUpdate();
break;
case PaintInvalidation:
- client->setShouldDoFullPaintInvalidation(true);
+ client->setShouldDoFullPaintInvalidation();
break;
case ParentOnlyInvalidation:
break;
}
}
-static bool shouldTransformOnTextPainting(RenderObject* object, AffineTransform& resourceTransform)
+static inline void removeFromCacheAndInvalidateDependencies(RenderObject* object, bool needsLayout)
{
ASSERT(object);
+ if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) {
+ if (RenderSVGResourceFilter* filter = resources->filter())
+ filter->removeClientFromCache(object);
- // This method should only be called for RenderObjects that deal with text rendering. Cmp. RenderObject.h's is*() methods.
- ASSERT(object->isSVGText() || object->isSVGTextPath() || object->isSVGInline());
-
- // In text drawing, the scaling part of the graphics context CTM is removed, compare SVGInlineTextBox::paintTextWithShadows.
- // So, we use that scaling factor here, too, and then push it down to pattern or gradient space
- // in order to keep the pattern or gradient correctly scaled.
- float scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(object);
- if (scalingFactor == 1)
- return false;
- resourceTransform.scale(scalingFactor);
- return true;
-}
+ if (RenderSVGResourceMasker* masker = resources->masker())
+ masker->removeClientFromCache(object);
-AffineTransform RenderSVGResourceContainer::computeResourceSpaceTransform(RenderObject* object, const AffineTransform& baseTransform, const SVGRenderStyle& svgStyle, unsigned short resourceMode)
-{
- AffineTransform computedSpaceTransform = baseTransform;
- if (resourceMode & ApplyToTextMode) {
- // Depending on the font scaling factor, we may need to apply an
- // additional transform (scale-factor) the paintserver, since text
- // painting removes the scale factor from the context. (See
- // SVGInlineTextBox::paintTextWithShadows.)
- AffineTransform additionalTextTransformation;
- if (shouldTransformOnTextPainting(object, additionalTextTransformation))
- computedSpaceTransform = additionalTextTransformation * computedSpaceTransform;
+ if (RenderSVGResourceClipper* clipper = resources->clipper())
+ clipper->removeClientFromCache(object);
}
- if (resourceMode & ApplyToStrokeMode) {
- // Non-scaling stroke needs to reset the transform back to the host transform.
- if (svgStyle.vectorEffect() == VE_NON_SCALING_STROKE)
- computedSpaceTransform = transformOnNonScalingStroke(object, computedSpaceTransform);
+
+ if (!object->node() || !object->node()->isSVGElement())
+ return;
+ SVGElementSet* dependencies = toSVGElement(object->node())->setOfIncomingReferences();
+ if (!dependencies)
+ return;
+
+ // We allow cycles in SVGDocumentExtensions reference sets in order to avoid expensive
+ // reference graph adjustments on changes, so we need to break possible cycles here.
+ // This strong reference is safe, as it is guaranteed that this set will be emptied
+ // at the end of recursion.
+ typedef WillBeHeapHashSet<RawPtrWillBeMember<SVGElement> > SVGElementSet;
+ DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<SVGElementSet>, invalidatingDependencies, (adoptPtrWillBeNoop(new SVGElementSet)));
+
+ SVGElementSet::iterator end = dependencies->end();
+ for (SVGElementSet::iterator it = dependencies->begin(); it != end; ++it) {
+ if (RenderObject* renderer = (*it)->renderer()) {
+ if (UNLIKELY(!invalidatingDependencies->add(*it).isNewEntry)) {
+ // Reference cycle: we are in process of invalidating this dependant.
+ continue;
+ }
+
+ RenderSVGResourceContainer::markForLayoutAndParentResourceInvalidation(renderer, needsLayout);
+ invalidatingDependencies->remove(*it);
+ }
}
- return computedSpaceTransform;
}
-// FIXME: This does not belong here.
-AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform)
+void RenderSVGResourceContainer::markForLayoutAndParentResourceInvalidation(RenderObject* object, bool needsLayout)
{
- if (!object->isSVGShape())
- return resourceTransform;
+ ASSERT(object);
+ ASSERT(object->node());
+
+ if (needsLayout && !object->documentBeingDestroyed())
+ object->setNeedsLayoutAndFullPaintInvalidation();
+
+ removeFromCacheAndInvalidateDependencies(object, needsLayout);
+
+ // Invalidate resources in ancestor chain, if needed.
+ RenderObject* current = object->parent();
+ while (current) {
+ removeFromCacheAndInvalidateDependencies(current, needsLayout);
- SVGGraphicsElement* element = toSVGGraphicsElement(object->node());
- AffineTransform transform = element->getScreenCTM(SVGGraphicsElement::DisallowStyleUpdate);
- transform *= resourceTransform;
- return transform;
+ if (current->isSVGResourceContainer()) {
+ // This will process the rest of the ancestors.
+ toRenderSVGResourceContainer(current)->removeAllClientsFromCache();
+ break;
+ }
+
+ current = current->parent();
+ }
}
}