WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch chunk 1 - v2
BreakCycle-chunk-1.diff (text/plain), 78.40 KB, created by
Nikolas Zimmermann
on 2010-07-28 01:52:10 PDT
(
hide
)
Description:
Patch chunk 1 - v2
Filename:
MIME Type:
Creator:
Nikolas Zimmermann
Created:
2010-07-28 01:52:10 PDT
Size:
78.40 KB
patch
obsolete
>Index: WebCore/ChangeLog >=================================================================== >--- WebCore/ChangeLog (revision 64192) >+++ WebCore/ChangeLog (working copy) >@@ -1,3 +1,98 @@ >+2010-07-28 Nikolas Zimmermann <nzimmermann@rim.com> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ WebKit shouldn't ignore resource cycles, but break them as Opera does >+ https://bugs.webkit.org/show_bug.cgi?id=43031 >+ >+ Don't ignore resources containing cyclic references, but break them, as discussed on SVG WG mailing lists - to be compatible with Opera which already does that. >+ >+ We used to lookup RenderSVGResourceContainers objects, by extracting the URI reference from the SVGRenderStyle, then utilizing getElementById() to lookup the >+ node, and access its renderer. Opera ignores such references, if they point to resources that contain cyclic references. Ignoring them would mean we have >+ to mutate the render style to empty the resource strings. That obviously doesn't work, as it would break expectations (getComputedStyle, etc.). >+ >+ Introduce a SVGResources class that stores pointers to all resources, that can be applied to a RenderObject (clipper/filter/markers/masker). >+ Add a SVGResourcesCache class, which is basically a HashMap<RenderObject*, SVGResources*>. Whenever a RenderObject receives style, we extract the URI references >+ from the SVGRenderStyle, look up the RenderSVGResourceContainer* objects, and store them in a SVGResources* class. Then we execute a cycle detection logic, >+ which detects cyclic references and breaks them. Breaking them means just nulling the pointer to the resource in the SVGResources object. Those SVGResources >+ objects are cached, and used throughout the render tree to access resources. This way it's guaranteed that all cyclic references are resolved until layout/paint >+ phase begins. >+ >+ This is the first chunk, which just adds the new SVGResources/SVGResourcesCache/SVGResourcesCycleSolver files, and does minor cleanups. >+ It's not yet glued in and doesn't affect any tests. >+ >+ * Android.mk: Add SVGResources.* / SVGResourcesCache.* / SVGResourcesCycleSolver.* to build. >+ * CMakeLists.txt: Ditto. >+ * WebCore.gypi: Ditto. >+ * WebCore.pro: Ditto. >+ * WebCore.vcproj/WebCore.vcproj: Ditto. >+ * WebCore.xcodeproj/project.pbxproj: Ditto. >+ * rendering/RenderInline.h: Make styleDidChange protected, RenderSVGInline wants to override it. >+ * rendering/RenderSVGAllInOne.cpp: Add SVGResources.* / SVGResourcesCache.* / SVGResourcesCycleSolver.* to build. >+ * rendering/RenderSVGHiddenContainer.h: >+ (WebCore::RenderSVGHiddenContainer::isSVGHiddenContainer): Make isSVGHiddenContainer() private and renderName() public. >+ * rendering/RenderSVGResourceContainer.cpp: Added. Moved most methods from the header in the implementation file. >+ (WebCore::RenderSVGResourceContainer::RenderSVGResourceContainer): >+ (WebCore::RenderSVGResourceContainer::~RenderSVGResourceContainer): >+ (WebCore::RenderSVGResourceContainer::idChanged): >+ (WebCore::RenderSVGResourceContainer::transformOnNonScalingStroke): >+ (WebCore::RenderSVGResourceContainer::containsCyclicReference): >+ * rendering/RenderSVGResourceContainer.h: Add stubs, that SVGResourcesCache uses - a follow-up patch will add the logic. >+ (WebCore::RenderSVGResourceContainer::addClient): >+ (WebCore::RenderSVGResourceContainer::removeClient): >+ * rendering/SVGResources.cpp: Added. Holds a list of resources applyable to a RenderObject (fill/stroke, mask/markers/clipper/filter) >+ (WebCore::paintingResourceFromSVGPaint): Helper function looking up a RenderSVGResource for a SVGPaint object. >+ (WebCore::registerPendingResource): Helper function that register a RenderSVGResource as pending in the SVGDocumentExtensions. >+ (WebCore::SVGResources::buildCachedResources): Build a list of resources for a RenderObject/RenderStyle pair, handles pending resources, if needed. >+ (WebCore::SVGResources::invalidateClient): Helper function that calls invalidateClient() on all resources. >+ (WebCore::SVGResources::resourceDestroyed): Helper function that calls invalidateClients() on a certain resource, and nulls it. >+ (WebCore::SVGResources::buildSetOfResources): Helper function that stashes all resources present in the SVGResources members in a HashSet, used in SVGResourcesCycleSolver. >+ (WebCore::SVGResources::resetClipper): Helper methods nulling a resource. >+ (WebCore::SVGResources::resetFilter): Ditto. >+ (WebCore::SVGResources::resetMarkerStart): Ditto. >+ (WebCore::SVGResources::resetMarkerMid): Ditto. >+ (WebCore::SVGResources::resetMarkerEnd): Ditto. >+ (WebCore::SVGResources::resetMasker): Ditto. >+ (WebCore::SVGResources::resetFill): Ditto. >+ (WebCore::SVGResources::resetStroke): Ditto. >+ (WebCore::SVGResources::dump): >+ * rendering/SVGResources.h: Added. >+ (WebCore::SVGResources::clipper): Accesor of the cached m_foo variable. >+ (WebCore::SVGResources::filter): Ditto. >+ (WebCore::SVGResources::markerStart): Ditto. >+ (WebCore::SVGResources::markerMid): Ditto. >+ (WebCore::SVGResources::markerEnd): Ditto. >+ (WebCore::SVGResources::masker): Ditto. >+ (WebCore::SVGResources::fill): Ditto. >+ (WebCore::SVGResources::stroke): Ditto. >+ * rendering/SVGResourcesCache.cpp: Added. Holds a HashMap<RenderObject*, SVGResources*> and utility functions that update/invalidate the cache. >+ (WebCore::SVGResourcesCache::SVGResourcesCache): >+ (WebCore::SVGResourcesCache::~SVGResourcesCache): >+ (WebCore::SVGResourcesCache::addResourcesFromRenderObject): Build a SVGResources object for a RenderObject and adds it to the cache, then detects & breaks cycles using SVGResourcesCycleSolver. >+ (WebCore::SVGResourcesCache::removeResourcesFromRenderObject): Remove a SVGResources object from the cache. >+ (WebCore::resourcesCacheFromRenderObject): Helper function, retrieving a SVGResourcesCache method from a RenderObject. >+ (WebCore::SVGResourcesCache::cachedResourcesForRenderObject): Returns a SVGResources object from the cache. >+ (WebCore::SVGResourcesCache::clientLayoutChanged): (static) Calls invalidateClient() on all resources that are used by the passed RenderObject. >+ (WebCore::SVGResourcesCache::clientStyleChanged): (static) Updates the cache (calling removeResourceFromRenderObject/addResourcesFrom...) and invalidates resources in the ancestor chain. >+ (WebCore::SVGResourcesCache::clientUpdatedFromElement): (static) Does the same, without invalidating the ancestor chain. >+ (WebCore::SVGResourcesCache::clientDestroyed): (static) Calls removeResourcesFromRenderObject() on the SVGResourcesCache, for the given renderer. >+ (WebCore::SVGResourcesCache::resourceDestroyed): (static) Updates all SVGResources objects in the cache, that refer to the given resource. >+ * rendering/SVGResourcesCache.h: Added. >+ * rendering/SVGResourcesCycleSolver.cpp: Added. Detects and breaks cyclic references, just the way Opera handles it. Break cycles as they are detected. >+ (WebCore::SVGResourcesCycleSolver::SVGResourcesCycleSolver): >+ (WebCore::SVGResourcesCycleSolver::~SVGResourcesCycleSolver): >+ (WebCore::SVGResourcesCycleSolver::resourceContainsCycles): Operates only on the render tree >+ (WebCore::targetReferenceFromResource): Helper method for chainableResourceContainsCycles(). >+ (WebCore::setFollowLinkForChainableResource): Ditto. >+ (WebCore::SVGResourcesCycleSolver::chainableResourceContainsCycles): Handles cycles for resources that are chainable through xlink:href (filter/gradient/pattern). >+ (WebCore::SVGResourcesCycleSolver::resolveCycles): Main method executing the cycle breaking logic, utilizing (chainableResource)resourceContainsCycles. >+ (WebCore::SVGResourcesCycleSolver::breakCycle): Nulls a resource in the given SVGResources* object, to avoid using an invalid resource while rendering/layouting. >+ * rendering/SVGResourcesCycleSolver.h: Added. >+ * svg/SVGDocumentExtensions.cpp: >+ (WebCore::SVGDocumentExtensions::SVGDocumentExtensions): Create SVGResourcesCache object once per SVGDocumentExtensions. >+ * svg/SVGDocumentExtensions.h: >+ (WebCore::SVGDocumentExtensions::resourcesCache): Expose accesor method for the SVGResourcesCache. >+ > 2010-07-28 Zoltan Herczeg <zherczeg@webkit.org> > > Reviewed by Nikolas Zimmermann. >Index: WebCore/Android.mk >=================================================================== >--- WebCore/Android.mk (revision 64192) >+++ WebCore/Android.mk (working copy) >@@ -638,6 +638,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ > rendering/RenderSVGModelObject.cpp \ > rendering/RenderSVGResource.cpp \ > rendering/RenderSVGResourceClipper.cpp \ >+ rendering/RenderSVGResourceContainer.cpp \ > rendering/RenderSVGResourceFilter.cpp \ > rendering/RenderSVGResourceGradient.cpp \ > rendering/RenderSVGResourceLinearGradient.cpp \ >@@ -687,6 +688,9 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ > rendering/SVGMarkerLayoutInfo.cpp \ > rendering/SVGRenderSupport.cpp \ > rendering/SVGRenderTreeAsText.cpp \ >+ rendering/SVGResources.cpp \ >+ rendering/SVGResourcesCache.cpp \ >+ rendering/SVGResourcesCycleSolver.cpp \ > rendering/SVGRootInlineBox.cpp \ > rendering/SVGShadowTreeElements.cpp \ > rendering/SVGTextChunkLayoutInfo.cpp \ >Index: WebCore/CMakeLists.txt >=================================================================== >--- WebCore/CMakeLists.txt (revision 64192) >+++ WebCore/CMakeLists.txt (working copy) >@@ -1544,6 +1544,7 @@ IF (ENABLE_SVG) > rendering/RenderSVGModelObject.cpp > rendering/RenderSVGResource.cpp > rendering/RenderSVGResourceClipper.cpp >+ rendering/RenderSVGResourceContainer.cpp > rendering/RenderSVGResourceFilter.cpp > rendering/RenderSVGResourceGradient.cpp > rendering/RenderSVGResourceLinearGradient.cpp >@@ -1566,6 +1567,9 @@ IF (ENABLE_SVG) > rendering/SVGMarkerLayoutInfo.cpp > rendering/SVGRenderSupport.cpp > rendering/SVGRenderTreeAsText.cpp >+ rendering/SVGResources.cpp >+ rendering/SVGResourcesCache.cpp >+ rendering/SVGResourcesCycleSolver.cpp > rendering/SVGRootInlineBox.cpp > rendering/SVGShadowTreeElements.cpp > rendering/SVGTextChunkLayoutInfo.cpp >Index: WebCore/WebCore.gypi >=================================================================== >--- WebCore/WebCore.gypi (revision 64192) >+++ WebCore/WebCore.gypi (working copy) >@@ -3312,6 +3312,8 @@ > 'rendering/RenderSVGResource.h', > 'rendering/RenderSVGResourceClipper.cpp', > 'rendering/RenderSVGResourceClipper.h', >+ 'rendering/RenderSVGResourceContainer.cpp', >+ 'rendering/RenderSVGResourceContainer.h', > 'rendering/RenderSVGResourceFilter.cpp', > 'rendering/RenderSVGResourceFilter.h', > 'rendering/RenderSVGResourceGradient.cpp', >@@ -3418,6 +3420,12 @@ > 'rendering/SVGRenderSupport.h', > 'rendering/SVGRenderTreeAsText.cpp', > 'rendering/SVGRenderTreeAsText.h', >+ 'rendering/SVGResources.cpp', >+ 'rendering/SVGResources.h', >+ 'rendering/SVGResourcesCache.cpp', >+ 'rendering/SVGResourcesCache.h', >+ 'rendering/SVGResourcesCycleSolver.cpp', >+ 'rendering/SVGResourcesCycleSolver.h', > 'rendering/SVGRootInlineBox.cpp', > 'rendering/SVGRootInlineBox.h', > 'rendering/SVGShadowTreeElements.cpp', >Index: WebCore/WebCore.pro >=================================================================== >--- WebCore/WebCore.pro (revision 64192) >+++ WebCore/WebCore.pro (working copy) >@@ -1826,6 +1826,7 @@ HEADERS += \ > rendering/RenderSVGModelObject.h \ > rendering/RenderSVGResource.h \ > rendering/RenderSVGResourceClipper.h \ >+ rendering/RenderSVGResourceContainer.h \ > rendering/RenderSVGResourceFilter.h \ > rendering/RenderSVGResourceGradient.h \ > rendering/RenderSVGResourceLinearGradient.h \ >@@ -1894,6 +1895,9 @@ HEADERS += \ > rendering/SVGMarkerLayoutInfo.h \ > rendering/SVGRenderSupport.h \ > rendering/SVGRenderTreeAsText.h \ >+ rendering/SVGResources.h \ >+ rendering/SVGResourcesCache.h \ >+ rendering/SVGResourcesCycleSolver.h \ > rendering/SVGRootInlineBox.h \ > rendering/SVGShadowTreeElements.h \ > rendering/SVGTextChunkLayoutInfo.h \ >@@ -2906,6 +2910,7 @@ contains(DEFINES, ENABLE_SVG=1) { > rendering/RenderSVGModelObject.cpp \ > rendering/RenderSVGResource.cpp \ > rendering/RenderSVGResourceClipper.cpp \ >+ rendering/RenderSVGResourceContainer.cpp \ > rendering/RenderSVGResourceFilter.cpp \ > rendering/RenderSVGResourceGradient.cpp \ > rendering/RenderSVGResourceLinearGradient.cpp \ >@@ -2927,6 +2932,9 @@ contains(DEFINES, ENABLE_SVG=1) { > rendering/SVGInlineTextBox.cpp \ > rendering/SVGMarkerLayoutInfo.cpp \ > rendering/SVGRenderSupport.cpp \ >+ rendering/SVGResources.cpp \ >+ rendering/SVGResourcesCache.cpp \ >+ rendering/SVGResourcesCycleSolver.cpp \ > rendering/SVGRootInlineBox.cpp \ > rendering/SVGShadowTreeElements.cpp \ > rendering/SVGTextChunkLayoutInfo.cpp \ >Index: WebCore/WebCore.vcproj/WebCore.vcproj >=================================================================== >--- WebCore/WebCore.vcproj/WebCore.vcproj (revision 64192) >+++ WebCore/WebCore.vcproj/WebCore.vcproj (working copy) >@@ -29885,6 +29885,62 @@ > > > </File> > <File >+ RelativePath="..\rendering\RenderSVGResourceContainer.cpp" >+ > >+ <FileConfiguration >+ Name="Debug|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Release|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_Internal|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_Cairo|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Release_Cairo|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_All|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ </File> >+ <File >+ RelativePath="..\rendering\RenderSVGResourceContainer.h" >+ > >+ </File> >+ <File > RelativePath="..\rendering\RenderSVGResourceFilter.cpp" > > > <FileConfiguration >@@ -31359,6 +31415,174 @@ > > > </File> > <File >+ RelativePath="..\rendering\SVGResources.cpp" >+ > >+ <FileConfiguration >+ Name="Debug|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Release|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_Internal|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_Cairo|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Release_Cairo|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_All|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ </File> >+ <File >+ RelativePath="..\rendering\SVGResources.h" >+ > >+ </File> >+ <File >+ RelativePath="..\rendering\SVGResourcesCache.cpp" >+ > >+ <FileConfiguration >+ Name="Debug|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Release|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_Internal|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_Cairo|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Release_Cairo|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_All|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ </File> >+ <File >+ RelativePath="..\rendering\SVGResourcesCache.h" >+ > >+ </File> >+ <File >+ RelativePath="..\rendering\SVGResourcesCycleSolver.cpp" >+ > >+ <FileConfiguration >+ Name="Debug|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Release|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_Internal|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_Cairo|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Release_Cairo|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ <FileConfiguration >+ Name="Debug_All|Win32" >+ ExcludedFromBuild="true" >+ > >+ <Tool >+ Name="VCCLCompilerTool" >+ /> >+ </FileConfiguration> >+ </File> >+ <File >+ RelativePath="..\rendering\SVGResourcesCycleSolver.h" >+ > >+ </File> >+ <File > RelativePath="..\rendering\SVGRootInlineBox.cpp" > > > <FileConfiguration >Index: WebCore/WebCore.xcodeproj/project.pbxproj >=================================================================== >--- WebCore/WebCore.xcodeproj/project.pbxproj (revision 64192) >+++ WebCore/WebCore.xcodeproj/project.pbxproj (working copy) >@@ -99,6 +99,10 @@ > 084CE5CC0F27DADC00E6240E /* WMLOptGroupElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 084CE5C80F27DADC00E6240E /* WMLOptGroupElement.h */; }; > 084CE5CD0F27DADC00E6240E /* WMLOptionElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 084CE5C90F27DADC00E6240E /* WMLOptionElement.cpp */; }; > 084CE5CE0F27DADC00E6240E /* WMLOptionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 084CE5CA0F27DADC00E6240E /* WMLOptionElement.h */; }; >+ 084D0E3C11F5816100081E1A /* SVGResources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 084D0E3811F5816100081E1A /* SVGResources.cpp */; }; >+ 084D0E3D11F5816100081E1A /* SVGResources.h in Headers */ = {isa = PBXBuildFile; fileRef = 084D0E3911F5816100081E1A /* SVGResources.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ 084D0E3E11F5816100081E1A /* SVGResourcesCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 084D0E3A11F5816100081E1A /* SVGResourcesCache.cpp */; }; >+ 084D0E3F11F5816100081E1A /* SVGResourcesCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 084D0E3B11F5816100081E1A /* SVGResourcesCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 084D2833110A7FCB0038239A /* SVGAnimatedPropertySynchronizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 084D2831110A7FCB0038239A /* SVGAnimatedPropertySynchronizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 084D2834110A7FCB0038239A /* SVGAnimatedPropertyTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 084D2832110A7FCB0038239A /* SVGAnimatedPropertyTraits.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 084DBAA10ED39D360038C226 /* WMLVariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 084DBA9D0ED39D350038C226 /* WMLVariables.cpp */; }; >@@ -112,10 +116,13 @@ > 08591AA50F085C4E009BACB1 /* InputElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 08591AA40F085C4E009BACB1 /* InputElement.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 085AFDC80F2977350061F2B3 /* WMLFormControlElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 085AFDC60F2977350061F2B3 /* WMLFormControlElement.cpp */; }; > 085AFDC90F2977350061F2B3 /* WMLFormControlElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 085AFDC70F2977350061F2B3 /* WMLFormControlElement.h */; settings = {ATTRIBUTES = (); }; }; >+ 085B05C211FAE16C004D65F6 /* SVGResourcesCycleSolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 085B05C011FAE16C004D65F6 /* SVGResourcesCycleSolver.cpp */; }; >+ 085B05C311FAE16C004D65F6 /* SVGResourcesCycleSolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 085B05C111FAE16C004D65F6 /* SVGResourcesCycleSolver.h */; }; > 085B92BA0EFDE73D00E6123C /* FormDataBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 085B92B80EFDE73D00E6123C /* FormDataBuilder.cpp */; }; > 085B92BB0EFDE73D00E6123C /* FormDataBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 085B92B90EFDE73D00E6123C /* FormDataBuilder.h */; settings = {ATTRIBUTES = (); }; }; > 0865CCE60EDDF51B00DF9EC3 /* WMLNoopElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0865CCE40EDDF51B00DF9EC3 /* WMLNoopElement.cpp */; }; > 0865CCE70EDDF51B00DF9EC3 /* WMLNoopElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 0865CCE50EDDF51B00DF9EC3 /* WMLNoopElement.h */; }; >+ 086A400611F6D6B7002CEC53 /* RenderSVGResourceContainer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 086A400511F6D6B7002CEC53 /* RenderSVGResourceContainer.cpp */; }; > 08700BE70F086C5300919419 /* InputElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08700BE60F086C5300919419 /* InputElement.cpp */; }; > 087281550F26B9B600AFC596 /* OptionElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 087281510F26B9B600AFC596 /* OptionElement.cpp */; }; > 087281560F26B9B600AFC596 /* OptionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 087281520F26B9B600AFC596 /* OptionElement.h */; }; >@@ -5754,6 +5761,10 @@ > 084CE5C80F27DADC00E6240E /* WMLOptGroupElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLOptGroupElement.h; sourceTree = "<group>"; }; > 084CE5C90F27DADC00E6240E /* WMLOptionElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLOptionElement.cpp; sourceTree = "<group>"; }; > 084CE5CA0F27DADC00E6240E /* WMLOptionElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLOptionElement.h; sourceTree = "<group>"; }; >+ 084D0E3811F5816100081E1A /* SVGResources.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGResources.cpp; sourceTree = "<group>"; }; >+ 084D0E3911F5816100081E1A /* SVGResources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGResources.h; sourceTree = "<group>"; }; >+ 084D0E3A11F5816100081E1A /* SVGResourcesCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGResourcesCache.cpp; sourceTree = "<group>"; }; >+ 084D0E3B11F5816100081E1A /* SVGResourcesCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGResourcesCache.h; sourceTree = "<group>"; }; > 084D2831110A7FCB0038239A /* SVGAnimatedPropertySynchronizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedPropertySynchronizer.h; sourceTree = "<group>"; }; > 084D2832110A7FCB0038239A /* SVGAnimatedPropertyTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedPropertyTraits.h; sourceTree = "<group>"; }; > 084DBA9D0ED39D350038C226 /* WMLVariables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLVariables.cpp; sourceTree = "<group>"; }; >@@ -5767,10 +5778,13 @@ > 08591AA40F085C4E009BACB1 /* InputElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputElement.h; sourceTree = "<group>"; }; > 085AFDC60F2977350061F2B3 /* WMLFormControlElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLFormControlElement.cpp; sourceTree = "<group>"; }; > 085AFDC70F2977350061F2B3 /* WMLFormControlElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLFormControlElement.h; sourceTree = "<group>"; }; >+ 085B05C011FAE16C004D65F6 /* SVGResourcesCycleSolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGResourcesCycleSolver.cpp; sourceTree = "<group>"; }; >+ 085B05C111FAE16C004D65F6 /* SVGResourcesCycleSolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGResourcesCycleSolver.h; sourceTree = "<group>"; }; > 085B92B80EFDE73D00E6123C /* FormDataBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FormDataBuilder.cpp; sourceTree = "<group>"; }; > 085B92B90EFDE73D00E6123C /* FormDataBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormDataBuilder.h; sourceTree = "<group>"; }; > 0865CCE40EDDF51B00DF9EC3 /* WMLNoopElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WMLNoopElement.cpp; sourceTree = "<group>"; }; > 0865CCE50EDDF51B00DF9EC3 /* WMLNoopElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMLNoopElement.h; sourceTree = "<group>"; }; >+ 086A400511F6D6B7002CEC53 /* RenderSVGResourceContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGResourceContainer.cpp; sourceTree = "<group>"; }; > 08700BE60F086C5300919419 /* InputElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InputElement.cpp; sourceTree = "<group>"; }; > 087281510F26B9B600AFC596 /* OptionElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptionElement.cpp; sourceTree = "<group>"; }; > 087281520F26B9B600AFC596 /* OptionElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionElement.h; sourceTree = "<group>"; }; >@@ -16766,6 +16780,7 @@ > 083192A7112B43050083C3B9 /* RenderSVGResource.h */, > 84BDA16911358D2A00DBF64C /* RenderSVGResourceClipper.cpp */, > 84BDA16A11358D2A00DBF64C /* RenderSVGResourceClipper.h */, >+ 086A400511F6D6B7002CEC53 /* RenderSVGResourceContainer.cpp */, > 08082372117987C100241DE8 /* RenderSVGResourceContainer.h */, > 841FDC241178C9BE00F8AC9B /* RenderSVGResourceFilter.cpp */, > 841FDC251178C9BE00F8AC9B /* RenderSVGResourceFilter.h */, >@@ -16852,6 +16867,12 @@ > A8F4FB930C169E7B002AFED5 /* SVGRenderSupport.h */, > B2EBDC9A0AF77E3400AE4A68 /* SVGRenderTreeAsText.cpp */, > B2EBDC9B0AF77E3400AE4A68 /* SVGRenderTreeAsText.h */, >+ 084D0E3811F5816100081E1A /* SVGResources.cpp */, >+ 084D0E3911F5816100081E1A /* SVGResources.h */, >+ 084D0E3A11F5816100081E1A /* SVGResourcesCache.cpp */, >+ 084D0E3B11F5816100081E1A /* SVGResourcesCache.h */, >+ 085B05C011FAE16C004D65F6 /* SVGResourcesCycleSolver.cpp */, >+ 085B05C111FAE16C004D65F6 /* SVGResourcesCycleSolver.h */, > 853CA9E40AEEC608002372DC /* SVGRootInlineBox.cpp */, > 853CA9E50AEEC608002372DC /* SVGRootInlineBox.h */, > 08DAB9C01103D9C1003E7ABA /* SVGShadowTreeElements.cpp */, >@@ -19847,6 +19868,9 @@ > E1BE512E0CF6C512002EA959 /* XSLTUnicodeSort.h in Headers */, > 97DD4D870FDF4D6E00ECF9A4 /* XSSAuditor.h in Headers */, > CE172E011136E8CE0062A533 /* ZoomMode.h in Headers */, >+ 084D0E3D11F5816100081E1A /* SVGResources.h in Headers */, >+ 084D0E3F11F5816100081E1A /* SVGResourcesCache.h in Headers */, >+ 085B05C311FAE16C004D65F6 /* SVGResourcesCycleSolver.h in Headers */, > ); > runOnlyForDeploymentPostprocessing = 0; > }; >@@ -22242,6 +22266,10 @@ > 93F19B0508245E59001E9ABC /* XSLTProcessorLibxslt.cpp in Sources */, > E1BE512D0CF6C512002EA959 /* XSLTUnicodeSort.cpp in Sources */, > 97DD4D860FDF4D6E00ECF9A4 /* XSSAuditor.cpp in Sources */, >+ 084D0E3C11F5816100081E1A /* SVGResources.cpp in Sources */, >+ 084D0E3E11F5816100081E1A /* SVGResourcesCache.cpp in Sources */, >+ 086A400611F6D6B7002CEC53 /* RenderSVGResourceContainer.cpp in Sources */, >+ 085B05C211FAE16C004D65F6 /* SVGResourcesCycleSolver.cpp in Sources */, > ); > runOnlyForDeploymentPostprocessing = 0; > }; >Index: WebCore/rendering/RenderInline.h >=================================================================== >--- WebCore/rendering/RenderInline.h (revision 64192) >+++ WebCore/rendering/RenderInline.h (working copy) >@@ -74,6 +74,9 @@ public: > int verticalPositionFromCache(bool firstLine) const; > void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; } > >+protected: >+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); >+ > private: > virtual RenderObjectChildList* virtualChildren() { return children(); } > virtual const RenderObjectChildList* virtualChildren() const { return children(); } >@@ -139,7 +142,6 @@ private: > virtual void addDashboardRegions(Vector<DashboardRegionValue>&); > #endif > >- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); > virtual void updateBoxModelInfoFromStyle(); > > static RenderInline* cloneInline(RenderInline* src); >Index: WebCore/rendering/RenderSVGAllInOne.cpp >=================================================================== >--- WebCore/rendering/RenderSVGAllInOne.cpp (revision 64192) >+++ WebCore/rendering/RenderSVGAllInOne.cpp (working copy) >@@ -35,6 +35,7 @@ > #include "RenderSVGModelObject.cpp" > #include "RenderSVGResource.cpp" > #include "RenderSVGResourceClipper.cpp" >+#include "RenderSVGResourceContainer.cpp" > #include "RenderSVGResourceFilter.cpp" > #include "RenderSVGResourceGradient.cpp" > #include "RenderSVGResourceLinearGradient.cpp" >@@ -57,6 +58,9 @@ > #include "SVGMarkerLayoutInfo.cpp" > #include "SVGRenderSupport.cpp" > #include "SVGRenderTreeAsText.cpp" >+#include "SVGResources.cpp" >+#include "SVGResourcesCache.cpp" >+#include "SVGResourcesCycleSolver.cpp" > #include "SVGRootInlineBox.cpp" > #include "SVGShadowTreeElements.cpp" > #include "SVGTextChunkLayoutInfo.cpp" >Index: WebCore/rendering/RenderSVGHiddenContainer.h >=================================================================== >--- WebCore/rendering/RenderSVGHiddenContainer.h (revision 64192) >+++ WebCore/rendering/RenderSVGHiddenContainer.h (working copy) >@@ -37,11 +37,10 @@ namespace WebCore { > public: > RenderSVGHiddenContainer(SVGStyledElement*); > >- private: >- virtual bool isSVGHiddenContainer() const { return true; } >- > virtual const char* renderName() const { return "RenderSVGHiddenContainer"; } > >+ private: >+ virtual bool isSVGHiddenContainer() const { return true; } > virtual bool requiresLayer() const { return false; } > > virtual void layout(); >Index: WebCore/rendering/RenderSVGResourceContainer.cpp >=================================================================== >--- WebCore/rendering/RenderSVGResourceContainer.cpp (revision 0) >+++ WebCore/rendering/RenderSVGResourceContainer.cpp (revision 0) >@@ -0,0 +1,131 @@ >+/* >+ * Copyright (C) Research In Motion Limited 2010. All rights reserved. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public License >+ * along with this library; see the file COPYING.LIB. If not, write to >+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ * >+ */ >+ >+#include "config.h" >+ >+#if ENABLE(SVG) >+#include "RenderSVGResourceContainer.h" >+ >+#include "RenderSVGShadowTreeRootContainer.h" >+#include "SVGStyledTransformableElement.h" >+ >+namespace WebCore { >+ >+RenderSVGResourceContainer::RenderSVGResourceContainer(SVGStyledElement* node) >+ : RenderSVGHiddenContainer(node) >+ , RenderSVGResource() >+ , m_id(node->hasID() ? node->getIdAttribute() : nullAtom) >+{ >+ ASSERT(node->document()); >+ node->document()->accessSVGExtensions()->addResource(m_id, this); >+} >+ >+RenderSVGResourceContainer::~RenderSVGResourceContainer() >+{ >+ ASSERT(node()); >+ ASSERT(node()->document()); >+ node()->document()->accessSVGExtensions()->removeResource(m_id); >+} >+ >+void RenderSVGResourceContainer::idChanged() >+{ >+ ASSERT(node()); >+ ASSERT(node()->document()); >+ SVGDocumentExtensions* extensions = node()->document()->accessSVGExtensions(); >+ >+ // Remove old id, that is guaranteed to be present in cache >+ extensions->removeResource(m_id); >+ m_id = static_cast<Element*>(node())->getIdAttribute(); >+ >+ // It's possible that an element is referencing us with the new id, and has to be notified that we're existing now >+ if (extensions->isPendingResource(m_id)) { >+ OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(m_id)); >+ if (clients->isEmpty()) >+ return; >+ >+ HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); >+ const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); >+ >+ for (; it != end; ++it) { >+ if (RenderObject* renderer = (*it)->renderer()) >+ renderer->setNeedsLayout(true); >+ } >+ } >+ >+ // Recache us with the new id >+ extensions->addResource(m_id, this); >+} >+ >+AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform) >+{ >+ if (!object->isRenderPath()) >+ return resourceTransform; >+ >+ SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node()); >+ AffineTransform transform = resourceTransform; >+ transform.multiply(element->getScreenCTM()); >+ return transform; >+} >+ >+bool RenderSVGResourceContainer::containsCyclicReference(const Node* startNode) const >+{ >+ ASSERT(startNode->document()); >+ >+ for (Node* node = startNode->firstChild(); node; node = node->nextSibling()) { >+ if (!node->isSVGElement()) >+ continue; >+ >+ RenderObject* renderer = node->renderer(); >+ if (!renderer) >+ continue; >+ >+ RenderStyle* style = renderer->style(); >+ if (!style) >+ continue; >+ >+ const SVGRenderStyle* svgStyle = style->svgStyle(); >+ ASSERT(svgStyle); >+ >+ // Let the class inheriting from us decide whether the child element references ourselves. >+ if (childElementReferencesResource(svgStyle, m_id)) >+ return true; >+ >+ // Dive into shadow tree to check for cycles there. >+ if (node->hasTagName(SVGNames::useTag)) { >+ ASSERT(renderer->isSVGShadowTreeRootContainer()); >+ if (Node* shadowRoot = static_cast<RenderSVGShadowTreeRootContainer*>(renderer)->rootElement()) { >+ if (containsCyclicReference(shadowRoot)) >+ return true; >+ } >+ >+ } >+ >+ if (node->hasChildNodes()) { >+ if (containsCyclicReference(node)) >+ return true; >+ } >+ } >+ >+ return false; >+} >+ >+} >+ >+#endif >Index: WebCore/rendering/RenderSVGResourceContainer.h >=================================================================== >--- WebCore/rendering/RenderSVGResourceContainer.h (revision 64192) >+++ WebCore/rendering/RenderSVGResourceContainer.h (working copy) >@@ -33,50 +33,10 @@ namespace WebCore { > class RenderSVGResourceContainer : public RenderSVGHiddenContainer, > public RenderSVGResource { > public: >- RenderSVGResourceContainer(SVGStyledElement* node) >- : RenderSVGHiddenContainer(node) >- , RenderSVGResource() >- , m_id(node->hasID() ? node->getIdAttribute() : nullAtom) >- { >- ASSERT(node->document()); >- node->document()->accessSVGExtensions()->addResource(m_id, this); >- } >- >- virtual ~RenderSVGResourceContainer() >- { >- ASSERT(node()); >- ASSERT(node()->document()); >- node()->document()->accessSVGExtensions()->removeResource(m_id); >- } >- >- void idChanged() >- { >- ASSERT(node()); >- ASSERT(node()->document()); >- SVGDocumentExtensions* extensions = node()->document()->accessSVGExtensions(); >- >- // Remove old id, that is guaranteed to be present in cache >- extensions->removeResource(m_id); >- m_id = static_cast<Element*>(node())->getIdAttribute(); >- >- // It's possible that an element is referencing us with the new id, and has to be notified that we're existing now >- if (extensions->isPendingResource(m_id)) { >- OwnPtr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(m_id)); >- if (clients->isEmpty()) >- return; >- >- HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); >- const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); >- >- for (; it != end; ++it) { >- if (RenderObject* renderer = (*it)->renderer()) >- renderer->setNeedsLayout(true); >- } >- } >- >- // Recache us with the new id >- extensions->addResource(m_id, this); >- } >+ RenderSVGResourceContainer(SVGStyledElement*); >+ virtual ~RenderSVGResourceContainer(); >+ >+ void idChanged(); > > virtual bool isSVGResourceContainer() const { return true; } > virtual bool drawsContents() { return false; } >@@ -84,58 +44,16 @@ public: > virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() { return this; } > virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const { return false; } > >- static AffineTransform transformOnNonScalingStroke(RenderObject* object, const AffineTransform resourceTransform) >- { >- if (!object->isRenderPath()) >- return resourceTransform; >- >- SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(object->node()); >- AffineTransform transform = resourceTransform; >- transform.multiply(element->getScreenCTM()); >- return transform; >- } >- >- bool containsCyclicReference(const Node* startNode) const >- { >- ASSERT(startNode->document()); >- >- for (Node* node = startNode->firstChild(); node; node = node->nextSibling()) { >- if (!node->isSVGElement()) >- continue; >- >- RenderObject* renderer = node->renderer(); >- if (!renderer) >- continue; >- >- RenderStyle* style = renderer->style(); >- if (!style) >- continue; >- >- const SVGRenderStyle* svgStyle = style->svgStyle(); >- ASSERT(svgStyle); >- >- // Let the class inheriting from us decide whether the child element references ourselves. >- if (childElementReferencesResource(svgStyle, m_id)) >- return true; >- >- // Dive into shadow tree to check for cycles there. >- if (node->hasTagName(SVGNames::useTag)) { >- ASSERT(renderer->isSVGShadowTreeRootContainer()); >- if (Node* shadowRoot = static_cast<RenderSVGShadowTreeRootContainer*>(renderer)->rootElement()) { >- if (containsCyclicReference(shadowRoot)) >- return true; >- } >- >- } >- >- if (node->hasChildNodes()) { >- if (containsCyclicReference(node)) >- return true; >- } >- } >- >- return false; >- } >+ static AffineTransform transformOnNonScalingStroke(RenderObject*, const AffineTransform& resourceTransform); >+ >+ bool containsCyclicReference(const Node* startNode) const; >+ >+private: >+ friend class SVGResourcesCache; >+ >+ // FIXME: No-ops for now, until follow-up patch on bug 43031 lands. >+ void addClient(RenderObject*) { } >+ void removeClient(RenderObject*) { } > > private: > AtomicString m_id; >Index: WebCore/rendering/SVGResources.cpp >=================================================================== >--- WebCore/rendering/SVGResources.cpp (revision 0) >+++ WebCore/rendering/SVGResources.cpp (revision 0) >@@ -0,0 +1,360 @@ >+/* >+ Copyright (C) Research In Motion Limited 2010. All rights reserved. >+ >+ This library is free software; you can redistribute it and/or >+ modify it under the terms of the GNU Library General Public >+ License as published by the Free Software Foundation; either >+ version 2 of the License, or (at your option) any later version. >+ >+ This library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Library General Public License for more details. >+ >+ You should have received a copy of the GNU Library General Public License >+ aint with this library; see the file COPYING.LIB. If not, write to >+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ Boston, MA 02110-1301, USA. >+*/ >+ >+#include "config.h" >+#include "SVGResources.h" >+ >+#if ENABLE(SVG) >+#include "RenderSVGResourceClipper.h" >+#include "RenderSVGResourceFilter.h" >+#include "RenderSVGResourceMarker.h" >+#include "RenderSVGResourceMasker.h" >+#include "SVGPaint.h" >+#include "SVGRenderStyle.h" >+#include "SVGURIReference.h" >+ >+namespace WebCore { >+ >+SVGResources::SVGResources() >+ : m_clipper(0) >+#if ENABLE(FILTERS) >+ , m_filter(0) >+#endif >+ , m_markerStart(0) >+ , m_markerMid(0) >+ , m_markerEnd(0) >+ , m_masker(0) >+ , m_fill(0) >+ , m_stroke(0) >+{ >+} >+ >+static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document* document, SVGPaint* paint, AtomicString& id, bool& hasPendingResource) >+{ >+ ASSERT(paint); >+ >+ SVGPaint::SVGPaintType paintType = paint->paintType(); >+ if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR) >+ return 0; >+ >+ id = SVGURIReference::getTarget(paint->uri()); >+ if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id)) >+ return container; >+ >+ hasPendingResource = true; >+ return 0; >+} >+ >+static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, Node* node) >+{ >+ ASSERT(node); >+ if (!node->isSVGElement()) >+ return; >+ >+ SVGElement* svgElement = static_cast<SVGElement*>(node); >+ if (!svgElement->isStyled()) >+ return; >+ >+ extensions->addPendingResource(id, static_cast<SVGStyledElement*>(svgElement)); >+} >+ >+bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRenderStyle* style) >+{ >+ ASSERT(object); >+ ASSERT(style); >+ >+ Node* node = object->node(); >+ ASSERT(node); >+ >+ Document* document = object->document(); >+ ASSERT(document); >+ >+ SVGDocumentExtensions* extensions = document->accessSVGExtensions(); >+ ASSERT(extensions); >+ >+ bool foundResources = false; >+ if (style->hasClipper()) { >+ AtomicString id(style->clipperResource()); >+ m_clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(document, id); >+ if (m_clipper) >+ foundResources = true; >+ else >+ registerPendingResource(extensions, id, node); >+ } >+ >+ if (style->hasMasker()) { >+ AtomicString id(style->maskerResource()); >+ m_masker = getRenderSVGResourceById<RenderSVGResourceMasker>(document, id); >+ if (m_masker) >+ foundResources = true; >+ else >+ registerPendingResource(extensions, id, node); >+ } >+ >+#if ENABLE(FILTERS) >+ if (style->hasFilter()) { >+ AtomicString id(style->filterResource()); >+ m_filter = getRenderSVGResourceById<RenderSVGResourceFilter>(document, id); >+ if (m_filter) >+ foundResources = true; >+ else >+ registerPendingResource(extensions, id, node); >+ } >+#endif >+ >+ if (style->hasMarkers()) { >+ AtomicString markerStartId(style->markerStartResource()); >+ m_markerStart = getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerStartId); >+ if (m_markerStart) >+ foundResources = true; >+ else >+ registerPendingResource(extensions, markerStartId, node); >+ >+ AtomicString markerMidId(style->markerMidResource()); >+ m_markerMid = getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerMidId); >+ if (m_markerMid) >+ foundResources = true; >+ else >+ registerPendingResource(extensions, markerMidId, node); >+ >+ AtomicString markerEndId(style->markerEndResource()); >+ m_markerEnd = getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerEndId); >+ if (m_markerEnd) >+ foundResources = true; >+ else >+ registerPendingResource(extensions, markerEndId, node); >+ } >+ >+ if (style->hasFill()) { >+ bool hasPendingResource = false; >+ AtomicString id; >+ m_fill = paintingResourceFromSVGPaint(document, style->fillPaint(), id, hasPendingResource); >+ if (m_fill) >+ foundResources = true; >+ else if (hasPendingResource) >+ registerPendingResource(extensions, id, node); >+ } >+ >+ if (style->hasStroke()) { >+ bool hasPendingResource = false; >+ AtomicString id; >+ m_stroke = paintingResourceFromSVGPaint(document, style->strokePaint(), id, hasPendingResource); >+ if (m_stroke) >+ foundResources = true; >+ else if (hasPendingResource) >+ registerPendingResource(extensions, id, node); >+ } >+ >+ return foundResources; >+} >+ >+void SVGResources::invalidateClient(RenderObject* object) const >+{ >+ // Ordinary resources >+ if (m_clipper) >+ m_clipper->invalidateClient(object); >+#if ENABLE(FILTERS) >+ if (m_filter) >+ m_filter->invalidateClient(object); >+#endif >+ if (m_masker) >+ m_masker->invalidateClient(object); >+ if (m_markerStart) >+ m_markerStart->invalidateClient(object); >+ if (m_markerMid) >+ m_markerMid->invalidateClient(object); >+ if (m_markerEnd) >+ m_markerEnd->invalidateClient(object); >+ >+ // Paint servers >+ if (m_fill) >+ m_fill->invalidateClient(object); >+ if (m_stroke) >+ m_stroke->invalidateClient(object); >+} >+ >+void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource) >+{ >+ ASSERT(resource); >+ >+ switch (resource->resourceType()) { >+ case MaskerResourceType: >+ if (m_masker == resource) { >+ m_masker->invalidateClients(); >+ m_masker = 0; >+ } >+ break; >+ case MarkerResourceType: >+ if (m_markerStart == resource) { >+ m_markerStart->invalidateClients(); >+ m_markerStart = 0; >+ } >+ >+ if (m_markerMid == resource) { >+ m_markerMid->invalidateClients(); >+ m_markerMid = 0; >+ } >+ >+ if (m_markerEnd == resource) { >+ m_markerEnd->invalidateClients(); >+ m_markerEnd = 0; >+ } >+ break; >+ case PatternResourceType: >+ case LinearGradientResourceType: >+ case RadialGradientResourceType: >+ if (m_fill == resource) { >+ m_fill->invalidateClients(); >+ m_fill = 0; >+ } >+ >+ if (m_stroke == resource) { >+ m_stroke->invalidateClients(); >+ m_stroke = 0; >+ } >+ break; >+#if ENABLE(FILTERS) >+ case FilterResourceType: >+ if (m_filter == resource) { >+ m_filter->invalidateClients(); >+ m_filter = 0; >+ } >+ break; >+#endif >+ case ClipperResourceType: >+ if (m_clipper == resource) { >+ m_clipper->invalidateClients(); >+ m_clipper = 0; >+ } >+ break; >+ case SolidColorResourceType: >+ ASSERT_NOT_REACHED(); >+ } >+} >+ >+void SVGResources::buildSetOfResources(HashSet<RenderSVGResourceContainer*>& set) >+{ >+ // Ordinary resources >+ if (m_clipper) >+ set.add(m_clipper); >+#if ENABLE(FILTERS) >+ if (m_filter) >+ set.add(m_filter); >+#endif >+ if (m_markerStart) >+ set.add(m_markerStart); >+ if (m_markerMid) >+ set.add(m_markerMid); >+ if (m_markerEnd) >+ set.add(m_markerEnd); >+ if (m_masker) >+ set.add(m_masker); >+ >+ // Paint servers >+ if (m_fill) >+ set.add(m_fill); >+ if (m_stroke) >+ set.add(m_stroke); >+} >+ >+void SVGResources::resetClipper() >+{ >+ ASSERT(m_clipper); >+ m_clipper = 0; >+} >+ >+#if ENABLE(FILTERS) >+void SVGResources::resetFilter() >+{ >+ ASSERT(m_filter); >+ m_filter = 0; >+} >+#endif >+ >+void SVGResources::resetMarkerStart() >+{ >+ ASSERT(m_markerStart); >+ m_markerStart = 0; >+} >+ >+void SVGResources::resetMarkerMid() >+{ >+ ASSERT(m_markerMid); >+ m_markerMid = 0; >+} >+ >+void SVGResources::resetMarkerEnd() >+{ >+ ASSERT(m_markerEnd); >+ m_markerEnd = 0; >+} >+ >+void SVGResources::resetMasker() >+{ >+ ASSERT(m_masker); >+ m_masker = 0; >+} >+ >+void SVGResources::resetFill() >+{ >+ ASSERT(m_fill); >+ m_fill = 0; >+} >+ >+void SVGResources::resetStroke() >+{ >+ ASSERT(m_stroke); >+ m_stroke = 0; >+} >+ >+#ifndef NDEBUG >+void SVGResources::dump(const RenderObject* object) >+{ >+ ASSERT(object); >+ ASSERT(object->node()); >+ >+ fprintf(stderr, "-> this=%p, SVGResources(renderer=%p, node=%p)\n", this, object, object->node()); >+ fprintf(stderr, " | DOM Tree:\n"); >+ object->node()->showTreeForThis(); >+ >+ fprintf(stderr, "\n | List of resources:\n"); >+ if (m_clipper) >+ fprintf(stderr, " |-> Clipper : %p (node=%p)\n", m_clipper, m_clipper->node()); >+#if ENABLE(FILTERS) >+ if (m_filter) >+ fprintf(stderr, " |-> Filter : %p (node=%p)\n", m_filter, m_filter->node()); >+#endif >+ if (m_markerStart) >+ fprintf(stderr, " |-> MarkerStart: %p (node=%p)\n", m_markerStart, m_markerStart->node()); >+ if (m_markerMid) >+ fprintf(stderr, " |-> MarkerMid : %p (node=%p)\n", m_markerMid, m_markerMid->node()); >+ if (m_markerEnd) >+ fprintf(stderr, " |-> MarkerEnd : %p (node=%p)\n", m_markerEnd, m_markerEnd->node()); >+ if (m_masker) >+ fprintf(stderr, " |-> Masker : %p (node=%p)\n", m_masker, m_masker->node()); >+ if (m_fill) >+ fprintf(stderr, " |-> Fill : %p (node=%p)\n", m_fill, m_fill->node()); >+ if (m_stroke) >+ fprintf(stderr, " |-> Stroke : %p (node=%p)\n", m_stroke, m_stroke->node()); >+} >+#endif >+ >+} >+ >+#endif >Index: WebCore/rendering/SVGResources.h >=================================================================== >--- WebCore/rendering/SVGResources.h (revision 0) >+++ WebCore/rendering/SVGResources.h (revision 0) >@@ -0,0 +1,103 @@ >+/* >+ Copyright (C) Research In Motion Limited 2010. All rights reserved. >+ >+ This library is free software; you can redistribute it and/or >+ modify it under the terms of the GNU Library General Public >+ License as published by the Free Software Foundation; either >+ version 2 of the License, or (at your option) any later version. >+ >+ This library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Library General Public License for more details. >+ >+ You should have received a copy of the GNU Library General Public License >+ aint with this library; see the file COPYING.LIB. If not, write to >+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ Boston, MA 02110-1301, USA. >+*/ >+ >+#ifndef SVGResources_h >+#define SVGResources_h >+ >+#if ENABLE(SVG) >+#include <wtf/HashSet.h> >+#include <wtf/Noncopyable.h> >+ >+namespace WebCore { >+ >+class Document; >+class RenderObject; >+class RenderSVGResourceClipper; >+class RenderSVGResourceContainer; >+class RenderSVGResourceFilter; >+class RenderSVGResourceMarker; >+class RenderSVGResourceMasker; >+class SVGRenderStyle; >+ >+// Holds a set of resources associated with a RenderObject >+class SVGResources { >+public: >+ SVGResources(); >+ >+ bool buildCachedResources(const RenderObject*, const SVGRenderStyle*); >+ >+ // Ordinary resources >+ RenderSVGResourceClipper* clipper() const { return m_clipper; } >+#if ENABLE(FILTERS) >+ RenderSVGResourceFilter* filter() const { return m_filter; } >+#endif >+ RenderSVGResourceMarker* markerStart() const { return m_markerStart; } >+ RenderSVGResourceMarker* markerMid() const { return m_markerMid; } >+ RenderSVGResourceMarker* markerEnd() const { return m_markerEnd; } >+ RenderSVGResourceMasker* masker() const { return m_masker; } >+ >+ // Paint servers >+ RenderSVGResourceContainer* fill() const { return m_fill; } >+ RenderSVGResourceContainer* stroke() const { return m_stroke; } >+ >+ void buildSetOfResources(HashSet<RenderSVGResourceContainer*>&); >+ >+ // Methods operating on all cached resources >+ void invalidateClient(RenderObject*) const; >+ void resourceDestroyed(RenderSVGResourceContainer*); >+ >+#ifndef NDEBUG >+ void dump(const RenderObject*); >+#endif >+ >+private: >+ friend class SVGResourcesCycleSolver; >+ >+ // Only used by SVGResourcesCache cycle detection logic >+ void resetClipper(); >+#if ENABLE(FILTERS) >+ void resetFilter(); >+#endif >+ void resetMarkerStart(); >+ void resetMarkerMid(); >+ void resetMarkerEnd(); >+ void resetMasker(); >+ void resetFill(); >+ void resetStroke(); >+ >+private: >+ // Ordinary resources >+ RenderSVGResourceClipper* m_clipper; >+#if ENABLE(FILTERS) >+ RenderSVGResourceFilter* m_filter; >+#endif >+ RenderSVGResourceMarker* m_markerStart; >+ RenderSVGResourceMarker* m_markerMid; >+ RenderSVGResourceMarker* m_markerEnd; >+ RenderSVGResourceMasker* m_masker; >+ >+ // Paint servers >+ RenderSVGResourceContainer* m_fill; >+ RenderSVGResourceContainer* m_stroke; >+}; >+ >+} >+ >+#endif >+#endif >Index: WebCore/rendering/SVGResourcesCache.cpp >=================================================================== >--- WebCore/rendering/SVGResourcesCache.cpp (revision 0) >+++ WebCore/rendering/SVGResourcesCache.cpp (revision 0) >@@ -0,0 +1,179 @@ >+/* >+ Copyright (C) Research In Motion Limited 2010. All rights reserved. >+ >+ This library is free software; you can redistribute it and/or >+ modify it under the terms of the GNU Library General Public >+ License as published by the Free Software Foundation; either >+ version 2 of the License, or (at your option) any later version. >+ >+ This library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Library General Public License for more details. >+ >+ You should have received a copy of the GNU Library General Public License >+ aint with this library; see the file COPYING.LIB. If not, write to >+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ Boston, MA 02110-1301, USA. >+*/ >+ >+#include "config.h" >+#include "SVGResourcesCache.h" >+ >+#if ENABLE(SVG) >+#include "RenderSVGResourceContainer.h" >+#include "SVGDocumentExtensions.h" >+#include "SVGResources.h" >+#include "SVGResourcesCycleSolver.h" >+ >+namespace WebCore { >+ >+SVGResourcesCache::SVGResourcesCache() >+{ >+} >+ >+SVGResourcesCache::~SVGResourcesCache() >+{ >+ if (m_cache.isEmpty()) >+ return; >+ >+ deleteAllValues(m_cache); >+ m_cache.clear(); >+} >+ >+void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const RenderStyle* style) >+{ >+ ASSERT(object); >+ ASSERT(style); >+ ASSERT(!m_cache.contains(object)); >+ >+ const SVGRenderStyle* svgStyle = style->svgStyle(); >+ ASSERT(svgStyle); >+ >+ // Build a list of all resources associated with the passed RenderObject >+ SVGResources* resources = new SVGResources; >+ if (!resources->buildCachedResources(object, svgStyle)) { >+ delete resources; >+ return; >+ } >+ >+ // Put object in cache. >+ m_cache.set(object, resources); >+ >+ // Run cycle-detection _afterwards_, so self-references can be caught as well. >+ SVGResourcesCycleSolver solver(object, resources); >+ solver.resolveCycles(); >+ >+ // Walk resources and register the render object at each resources. >+ HashSet<RenderSVGResourceContainer*> resourceSet; >+ resources->buildSetOfResources(resourceSet); >+ >+ HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end(); >+ for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it) >+ (*it)->addClient(object); >+} >+ >+void SVGResourcesCache::removeResourcesFromRenderObject(RenderObject* object) >+{ >+ if (!m_cache.contains(object)) >+ return; >+ >+ SVGResources* resources = m_cache.get(object); >+ >+ // Walk resources and register the render object at each resources. >+ HashSet<RenderSVGResourceContainer*> resourceSet; >+ resources->buildSetOfResources(resourceSet); >+ >+ HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end(); >+ for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it) >+ (*it)->removeClient(object); >+ >+ delete m_cache.take(object); >+} >+ >+static inline SVGResourcesCache* resourcesCacheFromRenderObject(RenderObject* renderer) >+{ >+ Document* document = renderer->document(); >+ ASSERT(document); >+ >+ SVGDocumentExtensions* extensions = document->accessSVGExtensions(); >+ ASSERT(extensions); >+ >+ SVGResourcesCache* cache = extensions->resourcesCache(); >+ ASSERT(cache); >+ >+ return cache; >+} >+ >+SVGResources* SVGResourcesCache::cachedResourcesForRenderObject(RenderObject* renderer) >+{ >+ ASSERT(renderer); >+ SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer); >+ if (!cache->m_cache.contains(renderer)) >+ return 0; >+ >+ return cache->m_cache.get(renderer); >+} >+ >+void SVGResourcesCache::clientLayoutChanged(RenderObject* object) >+{ >+ SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object); >+ if (!resources) >+ return; >+ >+ resources->invalidateClient(object); >+} >+ >+void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifference diff, const RenderStyle* newStyle) >+{ >+ ASSERT(renderer); >+ if (diff == StyleDifferenceEqual) >+ return; >+ >+ clientUpdatedFromElement(renderer, newStyle); >+ >+ // Invalidate resources in ancestor chain, if needed. >+ RenderObject* parent = renderer->parent(); >+ while (parent) { >+ if (parent->isSVGResourceContainer()) { >+ parent->toRenderSVGResourceContainer()->invalidateClients(); >+ break; >+ } >+ >+ parent = parent->parent(); >+ } >+} >+ >+void SVGResourcesCache::clientUpdatedFromElement(RenderObject* renderer, const RenderStyle* newStyle) >+{ >+ ASSERT(renderer); >+ ASSERT(renderer->parent()); >+ >+ SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer); >+ cache->removeResourcesFromRenderObject(renderer); >+ cache->addResourcesFromRenderObject(renderer, newStyle); >+} >+ >+void SVGResourcesCache::clientDestroyed(RenderObject* renderer) >+{ >+ ASSERT(renderer); >+ SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer); >+ cache->removeResourcesFromRenderObject(renderer); >+} >+ >+void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource) >+{ >+ ASSERT(resource); >+ SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource); >+ >+ // The resource itself may have clients, that need to be notified. >+ cache->removeResourcesFromRenderObject(resource); >+ >+ HashMap<RenderObject*, SVGResources*>::iterator end = cache->m_cache.end(); >+ for (HashMap<RenderObject*, SVGResources*>::iterator it = cache->m_cache.begin(); it != end; ++it) >+ it->second->resourceDestroyed(resource); >+} >+ >+} >+ >+#endif >Index: WebCore/rendering/SVGResourcesCache.h >=================================================================== >--- WebCore/rendering/SVGResourcesCache.h (revision 0) >+++ WebCore/rendering/SVGResourcesCache.h (revision 0) >@@ -0,0 +1,65 @@ >+/* >+ Copyright (C) Research In Motion Limited 2010. All rights reserved. >+ >+ This library is free software; you can redistribute it and/or >+ modify it under the terms of the GNU Library General Public >+ License as published by the Free Software Foundation; either >+ version 2 of the License, or (at your option) any later version. >+ >+ This library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Library General Public License for more details. >+ >+ You should have received a copy of the GNU Library General Public License >+ aint with this library; see the file COPYING.LIB. If not, write to >+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ Boston, MA 02110-1301, USA. >+*/ >+ >+#ifndef SVGResourcesCache_h >+#define SVGResourcesCache_h >+ >+#if ENABLE(SVG) >+#include "RenderStyleConstants.h" >+#include <wtf/HashMap.h> >+ >+namespace WebCore { >+ >+class RenderObject; >+class RenderStyle; >+class RenderSVGResourceContainer; >+class SVGResources; >+ >+class SVGResourcesCache : public Noncopyable { >+public: >+ SVGResourcesCache(); >+ ~SVGResourcesCache(); >+ >+ void addResourcesFromRenderObject(RenderObject*, const RenderStyle*); >+ void removeResourcesFromRenderObject(RenderObject*); >+ static SVGResources* cachedResourcesForRenderObject(RenderObject*); >+ >+ // Called from all SVG renderers destroy() methods - except for RenderSVGResourceContainer. >+ static void clientDestroyed(RenderObject*); >+ >+ // Called from all SVG renderers layout() methods. >+ static void clientLayoutChanged(RenderObject*); >+ >+ // Called from all SVG renderers styleDidChange() methods. >+ static void clientStyleChanged(RenderObject*, StyleDifference, const RenderStyle* newStyle); >+ >+ // Called from all SVG renderers updateFromElement() methods. >+ static void clientUpdatedFromElement(RenderObject*, const RenderStyle* newStyle); >+ >+ // Called from RenderSVGResourceContainer::destroy(). >+ static void resourceDestroyed(RenderSVGResourceContainer*); >+ >+private: >+ HashMap<RenderObject*, SVGResources*> m_cache; >+}; >+ >+} >+ >+#endif >+#endif >Index: WebCore/rendering/SVGResourcesCycleSolver.cpp >=================================================================== >--- WebCore/rendering/SVGResourcesCycleSolver.cpp (revision 0) >+++ WebCore/rendering/SVGResourcesCycleSolver.cpp (revision 0) >@@ -0,0 +1,296 @@ >+/* >+ Copyright (C) Research In Motion Limited 2010. All rights reserved. >+ >+ This library is free software; you can redistribute it and/or >+ modify it under the terms of the GNU Library General Public >+ License as published by the Free Software Foundation; either >+ version 2 of the License, or (at your option) any later version. >+ >+ This library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Library General Public License for more details. >+ >+ You should have received a copy of the GNU Library General Public License >+ aint with this library; see the file COPYING.LIB. If not, write to >+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ Boston, MA 02110-1301, USA. >+*/ >+ >+#include "config.h" >+#include "SVGResourcesCycleSolver.h" >+ >+// Set to a value > 0, to debug the resource cache. >+#define DEBUG_CYCLE_DETECTION 0 >+ >+#if ENABLE(SVG) >+#include "RenderSVGResourceClipper.h" >+#include "RenderSVGResourceFilter.h" >+#include "RenderSVGResourceMarker.h" >+#include "RenderSVGResourceMasker.h" >+#include "SVGFilterElement.h" >+#include "SVGGradientElement.h" >+#include "SVGPatternElement.h" >+#include "SVGResources.h" >+#include "SVGResourcesCache.h" >+ >+namespace WebCore { >+ >+SVGResourcesCycleSolver::SVGResourcesCycleSolver(RenderObject* renderer, SVGResources* resources) >+ : m_renderer(renderer) >+ , m_resources(resources) >+{ >+ ASSERT(m_renderer); >+ ASSERT(m_resources); >+} >+ >+SVGResourcesCycleSolver::~SVGResourcesCycleSolver() >+{ >+} >+ >+bool SVGResourcesCycleSolver::resourceContainsCycles(RenderObject* renderer) const >+{ >+ ASSERT(renderer); >+ >+ // First operate on the resources of the given renderer. >+ // <marker id="a"> <path marker-start="url(#b)"/> ... >+ // <marker id="b" marker-start="url(#a)"/> >+ if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer)) { >+ HashSet<RenderSVGResourceContainer*> resourceSet; >+ resources->buildSetOfResources(resourceSet); >+ >+ // Walk all resources and check wheter they reference any resource contained in the resources set. >+ HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end(); >+ for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it) { >+ if (m_allResources.contains(*it)) >+ return true; >+ } >+ } >+ >+ // Then operate on the child resources of the given renderer. >+ // <marker id="a"> <path marker-start="url(#b)"/> ... >+ // <marker id="b"> <path marker-start="url(#a)"/> ... >+ for (RenderObject* child = renderer->firstChild(); child; child = child->nextSibling()) { >+ SVGResources* childResources = SVGResourcesCache::cachedResourcesForRenderObject(child); >+ if (!childResources) >+ continue; >+ >+ // A child of the given 'resource' contains resources. >+ HashSet<RenderSVGResourceContainer*> childSet; >+ childResources->buildSetOfResources(childSet); >+ >+ // Walk all child resources and check wheter they reference any resource contained in the resources set. >+ HashSet<RenderSVGResourceContainer*>::iterator end = childSet.end(); >+ for (HashSet<RenderSVGResourceContainer*>::iterator it = childSet.begin(); it != end; ++it) { >+ if (m_allResources.contains(*it)) >+ return true; >+ } >+ >+ // Walk children recursively, stop immediately if we found a cycle >+ if (resourceContainsCycles(child)) >+ return true; >+ } >+ >+ return false; >+} >+ >+static inline String targetReferenceFromResource(SVGElement* element, bool& isValid) >+{ >+ String target; >+ if (element->hasTagName(SVGNames::patternTag)) >+ target = static_cast<SVGPatternElement*>(element)->href(); >+ else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag)) >+ target = static_cast<SVGGradientElement*>(element)->href(); >+ else if (element->hasTagName(SVGNames::filterTag)) >+ target = static_cast<SVGFilterElement*>(element)->href(); >+ else { >+ isValid = false; >+ return target; >+ } >+ >+ return SVGURIReference::getTarget(target); >+} >+ >+static inline void setFollowLinkForChainableResource(SVGElement*, bool) >+{ >+ // FIXME: Enable once the follow-up patch for bug 43031 lands >+} >+ >+bool SVGResourcesCycleSolver::chainableResourceContainsCycles(RenderSVGResourceContainer* container) const >+{ >+ ASSERT(container); >+ ASSERT(container->node()); >+ ASSERT(container->node()->isSVGElement()); >+ >+ // Chainable resources cycle detection is performed in the DOM tree. >+ SVGElement* element = static_cast<SVGElement*>(container->node()); >+ ASSERT(element); >+ >+ HashSet<SVGElement*> processedObjects; >+ >+ bool isValid = true; >+ String target = targetReferenceFromResource(element, isValid); >+ ASSERT(isValid); >+ >+ SVGElement* previousElement = element; >+ while (!target.isEmpty()) { >+ Node* targetNode = element->document()->getElementById(target); >+ if (!targetNode || !targetNode->isSVGElement()) >+ break; >+ >+ // Catch cylic chaining, otherwhise we'll run into an infinite loop here. >+ // <pattern id="foo" xlink:href="#bar"/> <pattern id="bar xlink:href="#foo"/> >+ SVGElement* targetElement = static_cast<SVGElement*>(targetNode); >+ >+ bool followLink = true; >+ if (processedObjects.contains(targetElement) || targetElement == element) >+ followLink = false; >+ >+ setFollowLinkForChainableResource(previousElement, followLink); >+ if (!followLink) >+ return false; >+ >+ previousElement = targetElement; >+ processedObjects.add(targetElement); >+ target = targetReferenceFromResource(targetElement, isValid); >+ if (!isValid) >+ break; >+ } >+ >+ // Couldn't find any direct cycle in the xlink:href chain, maybe there's an indirect one. >+ // <pattern id="foo" xlink:href="#bar"/> <pattern id="bar"> <rect fill="url(#foo)"... >+ HashSet<SVGElement*>::iterator end = processedObjects.end(); >+ for (HashSet<SVGElement*>::iterator it = processedObjects.begin(); it != end; ++it) { >+ RenderObject* renderer = (*it)->renderer(); >+ if (!renderer) >+ continue; >+ ASSERT(renderer->isSVGResourceContainer()); >+ if (m_allResources.contains(renderer->toRenderSVGResourceContainer())) >+ return true; >+ } >+ >+ return false; >+} >+ >+void SVGResourcesCycleSolver::resolveCycles() >+{ >+ ASSERT(m_allResources.isEmpty()); >+ >+#if DEBUG_CYCLE_DETECTION > 0 >+ fprintf(stderr, "\nBefore cycle detection:\n"); >+ m_resources->dump(m_renderer); >+#endif >+ >+ // Stash all resources into a HashSet for the ease of traversing. >+ HashSet<RenderSVGResourceContainer*> localResources; >+ m_resources->buildSetOfResources(localResources); >+ ASSERT(!localResources.isEmpty()); >+ >+ // Add all parent resource containers to the HashSet. >+ HashSet<RenderSVGResourceContainer*> parentResources; >+ RenderObject* parent = m_renderer->parent(); >+ while (parent) { >+ if (parent->isSVGResourceContainer()) >+ parentResources.add(parent->toRenderSVGResourceContainer()); >+ parent = parent->parent(); >+ } >+ >+#if DEBUG_CYCLE_DETECTION > 0 >+ fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n"); >+ { >+ fprintf(stderr, "Local resources:\n"); >+ HashSet<RenderSVGResourceContainer*>::iterator end = localResources.end(); >+ for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) >+ fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node()); >+ >+ fprintf(stderr, "Parent resources:\n"); >+ end = parentResources.end(); >+ for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it) >+ fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node()); >+ } >+#endif >+ >+ // Build combined set of local and parent resources. >+ m_allResources = localResources; >+ HashSet<RenderSVGResourceContainer*>::iterator end = parentResources.end(); >+ for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it) >+ m_allResources.add(*it); >+ >+ ASSERT(!m_allResources.isEmpty()); >+ >+ // The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer' >+ // references us (or wheter any of its kids references us) -> that's a cycle, we need to find and break it. >+ end = localResources.end(); >+ for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) { >+ RenderSVGResourceContainer* resource = *it; >+ >+ // Special handling for resources that can be chained using xlink:href - need to detect cycles as well! >+ switch (resource->resourceType()) { >+ case PatternResourceType: >+ case LinearGradientResourceType: >+ case RadialGradientResourceType: >+ case FilterResourceType: >+ if (chainableResourceContainsCycles(resource)) { >+ breakCycle(resource); >+ continue; >+ } >+ break; >+ default: >+ break; >+ } >+ >+ if (parentResources.contains(resource) || resourceContainsCycles(resource)) >+ breakCycle(resource); >+ } >+ >+#if DEBUG_CYCLE_DETECTION > 0 >+ fprintf(stderr, "\nAfter cycle detection:\n"); >+ m_resources->dump(m_renderer); >+#endif >+ >+ m_allResources.clear(); >+} >+ >+void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer* resourceLeadingToCycle) >+{ >+ ASSERT(resourceLeadingToCycle); >+ switch (resourceLeadingToCycle->resourceType()) { >+ case MaskerResourceType: >+ ASSERT(resourceLeadingToCycle == m_resources->masker()); >+ m_resources->resetMasker(); >+ break; >+ case MarkerResourceType: >+ ASSERT(resourceLeadingToCycle == m_resources->markerStart() || resourceLeadingToCycle == m_resources->markerMid() || resourceLeadingToCycle == m_resources->markerEnd()); >+ if (m_resources->markerStart() == resourceLeadingToCycle) >+ m_resources->resetMarkerStart(); >+ if (m_resources->markerMid() == resourceLeadingToCycle) >+ m_resources->resetMarkerMid(); >+ if (m_resources->markerEnd() == resourceLeadingToCycle) >+ m_resources->resetMarkerEnd(); >+ break; >+ case PatternResourceType: >+ case LinearGradientResourceType: >+ case RadialGradientResourceType: >+ ASSERT(resourceLeadingToCycle == m_resources->fill() || resourceLeadingToCycle == m_resources->stroke()); >+ if (m_resources->fill() == resourceLeadingToCycle) >+ m_resources->resetFill(); >+ if (m_resources->stroke() == resourceLeadingToCycle) >+ m_resources->resetStroke(); >+ break; >+ case FilterResourceType: >+ ASSERT(resourceLeadingToCycle == m_resources->filter()); >+ m_resources->resetFilter(); >+ break; >+ case ClipperResourceType: >+ ASSERT(resourceLeadingToCycle == m_resources->clipper()); >+ m_resources->resetClipper(); >+ break; >+ case SolidColorResourceType: >+ ASSERT_NOT_REACHED(); >+ break; >+ } >+} >+ >+} >+ >+#endif >Index: WebCore/rendering/SVGResourcesCycleSolver.h >=================================================================== >--- WebCore/rendering/SVGResourcesCycleSolver.h (revision 0) >+++ WebCore/rendering/SVGResourcesCycleSolver.h (revision 0) >@@ -0,0 +1,52 @@ >+/* >+ Copyright (C) Research In Motion Limited 2010. All rights reserved. >+ >+ This library is free software; you can redistribute it and/or >+ modify it under the terms of the GNU Library General Public >+ License as published by the Free Software Foundation; either >+ version 2 of the License, or (at your option) any later version. >+ >+ This library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Library General Public License for more details. >+ >+ You should have received a copy of the GNU Library General Public License >+ aint with this library; see the file COPYING.LIB. If not, write to >+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ Boston, MA 02110-1301, USA. >+*/ >+ >+#ifndef SVGResourcesCycleSolver_h >+#define SVGResourcesCycleSolver_h >+ >+#if ENABLE(SVG) >+#include <wtf/HashSet.h> >+ >+namespace WebCore { >+ >+class RenderObject; >+class RenderSVGResourceContainer; >+class SVGResources; >+ >+class SVGResourcesCycleSolver : public Noncopyable { >+public: >+ SVGResourcesCycleSolver(RenderObject*, SVGResources*); >+ ~SVGResourcesCycleSolver(); >+ >+ void resolveCycles(); >+ >+private: >+ bool resourceContainsCycles(RenderObject*) const; >+ bool chainableResourceContainsCycles(RenderSVGResourceContainer*) const; >+ void breakCycle(RenderSVGResourceContainer*); >+ >+ RenderObject* m_renderer; >+ SVGResources* m_resources; >+ HashSet<RenderSVGResourceContainer*> m_allResources; >+}; >+ >+} >+ >+#endif >+#endif >Index: WebCore/svg/SVGDocumentExtensions.cpp >=================================================================== >--- WebCore/svg/SVGDocumentExtensions.cpp (revision 64192) >+++ WebCore/svg/SVGDocumentExtensions.cpp (working copy) >@@ -34,16 +34,17 @@ > #include "Frame.h" > #include "FrameLoader.h" > #include "Page.h" >+#include "SMILTimeContainer.h" > #include "SVGSMILElement.h" > #include "SVGSVGElement.h" >-#include "SMILTimeContainer.h" >-#include "ScriptableDocumentParser.h" > #include "ScriptController.h" >+#include "ScriptableDocumentParser.h" > > namespace WebCore { > > SVGDocumentExtensions::SVGDocumentExtensions(Document* doc) > : m_doc(doc) >+ , m_resourcesCache(new SVGResourcesCache) > { > } > >Index: WebCore/svg/SVGDocumentExtensions.h >=================================================================== >--- WebCore/svg/SVGDocumentExtensions.h (revision 64192) >+++ WebCore/svg/SVGDocumentExtensions.h (working copy) >@@ -25,6 +25,7 @@ > > #if ENABLE(SVG) > #include "AtomicStringHash.h" >+#include "SVGResourcesCache.h" > #include "StringImpl.h" > #include <wtf/HashMap.h> > #include <wtf/HashSet.h> >@@ -59,11 +60,14 @@ public: > void reportWarning(const String&); > void reportError(const String&); > >+ SVGResourcesCache* resourcesCache() const { return m_resourcesCache.get(); } >+ > private: > Document* m_doc; // weak reference > HashSet<SVGSVGElement*> m_timeContainers; // For SVG 1.2 support this will need to be made more general. > HashMap<AtomicString, RenderSVGResourceContainer*> m_resources; > HashMap<AtomicString, HashSet<SVGStyledElement*>*> m_pendingResources; >+ OwnPtr<SVGResourcesCache> m_resourcesCache; > > SVGDocumentExtensions(const SVGDocumentExtensions&); > SVGDocumentExtensions& operator=(const SVGDocumentExtensions&);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
krit
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 43031
:
62673
|
62674
|
62716
|
62803
|
62837
|
62838
|
62937
|
62938