[SVG Masking] Add support for referencing <mask> elements from -webkit-mask-image
authorstavila@adobe.com <stavila@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Dec 2014 17:05:12 +0000 (17:05 +0000)
committerstavila@adobe.com <stavila@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Dec 2014 17:05:12 +0000 (17:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=139092

Reviewed by Simon Fraser.

This patch improves the -webkit-mask-image property by allowing it to reference
a <mask> element defined in an inline or external SVG document.
Up until now, each image to be used as a mask consisted of a FillLayer object
whose m_image member represented the mask. Now, in order to accomodate
<mask> elements referenced by a fragment identifier (e.g. file.svg#mask1)
a new class was created (MaskImageOperation) and added as a member of the
FillLayer. As such, from now on, all FillLayer objects used for masking will
store the masking information in this new member.
When parsing the -webkit-mask-image property (or the -webkit-mask shorthand)
a new MaskImageOperation object is created for each image. If the value represents
an external URL, a pending SVG document will be created which will be loaded
during the phase that loads the pending resources. When the download is complete,
the MaskImageOperation is notified by the CachedSVGDocument class and checks if
the received download is a valid SVG and the requested fragment identifier
actually exists and identifies a <mask> element. If it does, that element's
renderer (of type RenderSVGResourceMasker) will be used when painting the mask layers.
Otherwise, the MaskImageOperation class will use the already downloaded data
buffer to create a CachedImage from it and use that instead, basically emulating
the previous behavior, when only images were accepted. This ensures that all existing
behavior, like painting entire SVGs, painting normal images (e.g. PNG/JPG), painting
generated images (e.g. linear-gradient) works as it did before.

No new tests required, this patch doesn't change any current functionality.
It only adds support for referencing <mask> elements for the -webkit-mask-image
property. This is sub-part 1 of the bigger patch https://bugs.webkit.org/show_bug.cgi?id=129682.

* CMakeLists.txt:
* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.vcxproj/WebCore.vcxproj.filters:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSValue.cpp:
(WebCore::CSSValue::cssText):
(WebCore::CSSValue::destroy):
* css/CSSValue.h:
(WebCore::CSSValue::isWebKitCSSResourceValue):
* css/StyleResolver.cpp:
(WebCore::StyleResolver::State::clear):
(WebCore::StyleResolver::createMaskImageOperations):
* css/StyleResolver.h:
(WebCore::StyleResolver::State::maskImagesWithPendingSVGDocuments):
* css/WebKitCSSResourceValue.cpp: Added.
(WebCore::WebKitCSSResourceValue::WebKitCSSResourceValue):
(WebCore::WebKitCSSResourceValue::customCSSText):
(WebCore::WebKitCSSResourceValue::isCSSValueNone):
* css/WebKitCSSResourceValue.h: Added.
(WebCore::WebKitCSSResourceValue::create):
(WebCore::WebKitCSSResourceValue::innerValue):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::addCachedResource):
* loader/cache/CachedResourceLoader.h:
* loader/cache/CachedSVGDocument.cpp:
(WebCore::CachedSVGDocument::CachedSVGDocument):
(WebCore::CachedSVGDocument::finishLoading):
* loader/cache/CachedSVGDocument.h:
* loader/cache/CachedSVGDocumentReference.cpp:
(WebCore::CachedSVGDocumentReference::CachedSVGDocumentReference):
(WebCore::CachedSVGDocumentReference::~CachedSVGDocumentReference):
(WebCore::CachedSVGDocumentReference::load):
* loader/cache/CachedSVGDocumentReference.h:
* page/FrameView.cpp:
(WebCore::FrameView::isSVGDocument):
* page/FrameView.h:
* page/Page.cpp:
(WebCore::Page::createPageFromBuffer):
* page/Page.h:
* platform/ScrollView.h:
(WebCore::ScrollView::isSVGDocument):
* platform/graphics/MaskImageOperation.cpp: Added.
(WebCore::MaskImageOperation::create):
(WebCore::MaskImageOperation::MaskImageOperation):
(WebCore::MaskImageOperation::~MaskImageOperation):
(WebCore::MaskImageOperation::isCSSValueNone):
(WebCore::MaskImageOperation::cssValue):
(WebCore::MaskImageOperation::isMaskLoaded):
(WebCore::MaskImageOperation::setRenderLayerImageClient):
(WebCore::MaskImageOperation::addRendererImageClient):
(WebCore::MaskImageOperation::removeRendererImageClient):
(WebCore::MaskImageOperation::getOrCreateCachedSVGDocumentReference):
(WebCore::MaskImageOperation::notifyFinished): This is the method that gets called when the document has finished
downloading and checks if it can find a valid <mask> element.
(WebCore::MaskImageOperation::drawMask):
(WebCore::MaskImageOperation::getSVGMasker):
* platform/graphics/MaskImageOperation.h: Added.
* rendering/RenderBoxModelObject.cpp: The BackgroundImageGeometry class was moved out of RenderBoxModelObject in
order to be used as a parameter for other methods. This was necessary to avoid having methods with very many parameters.
(WebCore::BackgroundImageGeometry::setNoRepeatX):
(WebCore::BackgroundImageGeometry::setNoRepeatY):
(WebCore::BackgroundImageGeometry::useFixedAttachment):
(WebCore::BackgroundImageGeometry::clip):
(WebCore::BackgroundImageGeometry::relativePhase):
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatX): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatY): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::useFixedAttachment): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::clip): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::relativePhase): Deleted.
* rendering/RenderBoxModelObject.h:
(WebCore::BackgroundImageGeometry::BackgroundImageGeometry):
(WebCore::BackgroundImageGeometry::destOrigin):
(WebCore::BackgroundImageGeometry::setDestOrigin):
(WebCore::BackgroundImageGeometry::destRect):
(WebCore::BackgroundImageGeometry::setDestRect):
(WebCore::BackgroundImageGeometry::phase):
(WebCore::BackgroundImageGeometry::setPhase):
(WebCore::BackgroundImageGeometry::tileSize):
(WebCore::BackgroundImageGeometry::setTileSize):
(WebCore::BackgroundImageGeometry::spaceSize):
(WebCore::BackgroundImageGeometry::setSpaceSize):
(WebCore::BackgroundImageGeometry::setPhaseX):
(WebCore::BackgroundImageGeometry::setPhaseY):
(WebCore::BackgroundImageGeometry::setHasNonLocalGeometry):
(WebCore::BackgroundImageGeometry::hasNonLocalGeometry):
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::BackgroundImageGeometry): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::destOrigin): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setDestOrigin): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::destRect): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setDestRect): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::phase): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setPhase): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::tileSize): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setTileSize): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::spaceSize): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setSpaceSize): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setPhaseX): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setPhaseY): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setHasNonLocalGeometry): Deleted.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::hasNonLocalGeometry): Deleted.
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::RenderLayer):
(WebCore::RenderLayer::~RenderLayer):
* rendering/RenderLayer.h:
* rendering/RenderLayerMaskImageInfo.cpp: Added.
(WebCore::RenderLayer::MaskImageInfo::layerToMaskMap): Returns a static map that links MaskImageInfo objects to RenderLayers.
(WebCore::RenderLayer::MaskImageInfo::getIfExists): Returns the MaskImageInfo associated with a specific RenderLayer.
(WebCore::RenderLayer::MaskImageInfo::get): Returns the MaskImageInfo associated with a specific RenderLayer (creates it if necessary).
(WebCore::RenderLayer::MaskImageInfo::remove): Removes the MaskImageInfo associated with a specific RenderLayer.
(WebCore::RenderLayer::MaskImageInfo::MaskImageInfo):
(WebCore::RenderLayer::MaskImageInfo::~MaskImageInfo):
(WebCore::RenderLayer::MaskImageInfo::notifyFinished): Gets called when the SVG document finished loading, triggers repaint.
(WebCore::RenderLayer::MaskImageInfo::imageChanged): Gets called when the image object changed, triggers repaint.
(WebCore::RenderLayer::MaskImageInfo::updateMaskImageClients): Goes through all mask layers and sets image/SVG clients.
Updates list of internal and external SVG references.
(WebCore::RenderLayer::MaskImageInfo::removeMaskImageClients): Removes all image/SVG clients and clears lists of internal and external SVG references.
* rendering/RenderLayerMaskImageInfo.h: Added.
* rendering/RenderObject.h:
(WebCore::RenderObject::isRenderSVGResourceMasker):
* rendering/style/FillLayer.cpp:
(WebCore::FillLayer::FillLayer):
(WebCore::FillLayer::operator=):
(WebCore::FillLayer::operator==):
(WebCore::FillLayer::cullEmptyLayers):
(WebCore::FillLayer::hasNonEmptyMaskImage):
(WebCore::FillLayer::imagesAreLoaded):
* rendering/style/FillLayer.h:
(WebCore::FillLayer::maskImage):
(WebCore::FillLayer::imageOrMaskImage):
(WebCore::FillLayer::setMaskImage):
(WebCore::FillLayer::clearMaskImage):
(WebCore::FillLayer::hasMaskImage):
* rendering/svg/RenderSVGResourceMasker.cpp:
(WebCore::RenderSVGResourceMasker::applySVGMask):
(WebCore::RenderSVGResourceMasker::applyResource):
(WebCore::RenderSVGResourceMasker::drawMaskForRenderer):
* rendering/svg/RenderSVGResourceMasker.h:
* svg/SVGMaskElement.cpp:
(WebCore::SVGMaskElement::createElementRenderer):
(WebCore::SVGMaskElement::addClientRenderLayer):
(WebCore::SVGMaskElement::removeClientRenderLayer):
* svg/SVGMaskElement.h:
* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::setCachedDocument):
* svg/graphics/SVGImage.cpp:
(WebCore::SVGImage::dataChanged):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@176798 268f45cc-cd09-0410-ab3c-d52691b4dbfc

38 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSValue.cpp
Source/WebCore/css/CSSValue.h
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h
Source/WebCore/css/WebKitCSSResourceValue.cpp [new file with mode: 0644]
Source/WebCore/css/WebKitCSSResourceValue.h [new file with mode: 0644]
Source/WebCore/loader/cache/CachedResourceLoader.cpp
Source/WebCore/loader/cache/CachedResourceLoader.h
Source/WebCore/loader/cache/CachedSVGDocument.cpp
Source/WebCore/loader/cache/CachedSVGDocument.h
Source/WebCore/loader/cache/CachedSVGDocumentReference.cpp
Source/WebCore/loader/cache/CachedSVGDocumentReference.h
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebCore/platform/ScrollView.h
Source/WebCore/platform/graphics/MaskImageOperation.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/MaskImageOperation.h [new file with mode: 0644]
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderBoxModelObject.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerMaskImageInfo.cpp [new file with mode: 0644]
Source/WebCore/rendering/RenderLayerMaskImageInfo.h [new file with mode: 0644]
Source/WebCore/rendering/style/FillLayer.cpp
Source/WebCore/rendering/style/FillLayer.h
Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
Source/WebCore/rendering/svg/RenderSVGResourceMasker.h
Source/WebCore/svg/SVGMaskElement.cpp
Source/WebCore/svg/SVGMaskElement.h
Source/WebCore/svg/SVGUseElement.cpp
Source/WebCore/svg/graphics/SVGImage.cpp

index 97c2329..c9ac025 100644 (file)
@@ -1289,6 +1289,7 @@ set(WebCore_SOURCES
     css/TransformFunctions.cpp
     css/ViewportStyleResolver.cpp
     css/WebKitCSSFilterValue.cpp
+    css/WebKitCSSResourceValue.cpp
     css/CSSKeyframeRule.cpp
     css/CSSKeyframesRule.cpp
     css/WebKitCSSMatrix.cpp
@@ -2089,6 +2090,7 @@ set(WebCore_SOURCES
     platform/graphics/ISOVTTCue.cpp
     platform/graphics/LayoutBoxExtent.cpp
     platform/graphics/LayoutRect.cpp
+    platform/graphics/MaskImageOperation.cpp
     platform/graphics/MediaPlayer.cpp
     platform/graphics/Path.cpp
     platform/graphics/PathTraversalState.cpp
@@ -2295,6 +2297,7 @@ set(WebCore_SOURCES
     rendering/RenderLayerBacking.cpp
     rendering/RenderLayerCompositor.cpp
     rendering/RenderLayerFilterInfo.cpp
+    rendering/RenderLayerMaskImageInfo.cpp
     rendering/RenderLayerModelObject.cpp
     rendering/RenderLineBoxList.cpp
     rendering/RenderLineBreak.cpp
index b36aec8..55607e7 100644 (file)
@@ -1,3 +1,183 @@
+2014-12-04  Radu Stavila  <stavila@adobe.com>
+
+        [SVG Masking] Add support for referencing <mask> elements from -webkit-mask-image
+        https://bugs.webkit.org/show_bug.cgi?id=139092
+
+        Reviewed by Simon Fraser.
+
+        This patch improves the -webkit-mask-image property by allowing it to reference
+        a <mask> element defined in an inline or external SVG document.
+        Up until now, each image to be used as a mask consisted of a FillLayer object 
+        whose m_image member represented the mask. Now, in order to accomodate
+        <mask> elements referenced by a fragment identifier (e.g. file.svg#mask1)
+        a new class was created (MaskImageOperation) and added as a member of the 
+        FillLayer. As such, from now on, all FillLayer objects used for masking will
+        store the masking information in this new member.
+        When parsing the -webkit-mask-image property (or the -webkit-mask shorthand)
+        a new MaskImageOperation object is created for each image. If the value represents
+        an external URL, a pending SVG document will be created which will be loaded 
+        during the phase that loads the pending resources. When the download is complete,
+        the MaskImageOperation is notified by the CachedSVGDocument class and checks if
+        the received download is a valid SVG and the requested fragment identifier
+        actually exists and identifies a <mask> element. If it does, that element's
+        renderer (of type RenderSVGResourceMasker) will be used when painting the mask layers.
+        Otherwise, the MaskImageOperation class will use the already downloaded data 
+        buffer to create a CachedImage from it and use that instead, basically emulating
+        the previous behavior, when only images were accepted. This ensures that all existing
+        behavior, like painting entire SVGs, painting normal images (e.g. PNG/JPG), painting
+        generated images (e.g. linear-gradient) works as it did before.
+
+        No new tests required, this patch doesn't change any current functionality. 
+        It only adds support for referencing <mask> elements for the -webkit-mask-image 
+        property. This is sub-part 1 of the bigger patch https://bugs.webkit.org/show_bug.cgi?id=129682.
+
+        * CMakeLists.txt:
+        * WebCore.vcxproj/WebCore.vcxproj:
+        * WebCore.vcxproj/WebCore.vcxproj.filters:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSValue.cpp:
+        (WebCore::CSSValue::cssText):
+        (WebCore::CSSValue::destroy):
+        * css/CSSValue.h:
+        (WebCore::CSSValue::isWebKitCSSResourceValue):
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::State::clear):
+        (WebCore::StyleResolver::createMaskImageOperations):
+        * css/StyleResolver.h:
+        (WebCore::StyleResolver::State::maskImagesWithPendingSVGDocuments):
+        * css/WebKitCSSResourceValue.cpp: Added.
+        (WebCore::WebKitCSSResourceValue::WebKitCSSResourceValue):
+        (WebCore::WebKitCSSResourceValue::customCSSText):
+        (WebCore::WebKitCSSResourceValue::isCSSValueNone):
+        * css/WebKitCSSResourceValue.h: Added.
+        (WebCore::WebKitCSSResourceValue::create):
+        (WebCore::WebKitCSSResourceValue::innerValue):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::addCachedResource):
+        * loader/cache/CachedResourceLoader.h:
+        * loader/cache/CachedSVGDocument.cpp:
+        (WebCore::CachedSVGDocument::CachedSVGDocument):
+        (WebCore::CachedSVGDocument::finishLoading):
+        * loader/cache/CachedSVGDocument.h:
+        * loader/cache/CachedSVGDocumentReference.cpp:
+        (WebCore::CachedSVGDocumentReference::CachedSVGDocumentReference):
+        (WebCore::CachedSVGDocumentReference::~CachedSVGDocumentReference):
+        (WebCore::CachedSVGDocumentReference::load):
+        * loader/cache/CachedSVGDocumentReference.h:
+        * page/FrameView.cpp:
+        (WebCore::FrameView::isSVGDocument):
+        * page/FrameView.h:
+        * page/Page.cpp:
+        (WebCore::Page::createPageFromBuffer):
+        * page/Page.h:
+        * platform/ScrollView.h:
+        (WebCore::ScrollView::isSVGDocument):
+        * platform/graphics/MaskImageOperation.cpp: Added.
+        (WebCore::MaskImageOperation::create):
+        (WebCore::MaskImageOperation::MaskImageOperation):
+        (WebCore::MaskImageOperation::~MaskImageOperation):
+        (WebCore::MaskImageOperation::isCSSValueNone):
+        (WebCore::MaskImageOperation::cssValue):
+        (WebCore::MaskImageOperation::isMaskLoaded):
+        (WebCore::MaskImageOperation::setRenderLayerImageClient):
+        (WebCore::MaskImageOperation::addRendererImageClient):
+        (WebCore::MaskImageOperation::removeRendererImageClient):
+        (WebCore::MaskImageOperation::getOrCreateCachedSVGDocumentReference):
+        (WebCore::MaskImageOperation::notifyFinished): This is the method that gets called when the document has finished 
+        downloading and checks if it can find a valid <mask> element.
+        (WebCore::MaskImageOperation::drawMask):
+        (WebCore::MaskImageOperation::getSVGMasker):
+        * platform/graphics/MaskImageOperation.h: Added.
+        * rendering/RenderBoxModelObject.cpp: The BackgroundImageGeometry class was moved out of RenderBoxModelObject in 
+        order to be used as a parameter for other methods. This was necessary to avoid having methods with very many parameters.
+        (WebCore::BackgroundImageGeometry::setNoRepeatX):
+        (WebCore::BackgroundImageGeometry::setNoRepeatY):
+        (WebCore::BackgroundImageGeometry::useFixedAttachment):
+        (WebCore::BackgroundImageGeometry::clip):
+        (WebCore::BackgroundImageGeometry::relativePhase):
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatX): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatY): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::useFixedAttachment): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::clip): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::relativePhase): Deleted.
+        * rendering/RenderBoxModelObject.h:
+        (WebCore::BackgroundImageGeometry::BackgroundImageGeometry):
+        (WebCore::BackgroundImageGeometry::destOrigin):
+        (WebCore::BackgroundImageGeometry::setDestOrigin):
+        (WebCore::BackgroundImageGeometry::destRect):
+        (WebCore::BackgroundImageGeometry::setDestRect):
+        (WebCore::BackgroundImageGeometry::phase):
+        (WebCore::BackgroundImageGeometry::setPhase):
+        (WebCore::BackgroundImageGeometry::tileSize):
+        (WebCore::BackgroundImageGeometry::setTileSize):
+        (WebCore::BackgroundImageGeometry::spaceSize):
+        (WebCore::BackgroundImageGeometry::setSpaceSize):
+        (WebCore::BackgroundImageGeometry::setPhaseX):
+        (WebCore::BackgroundImageGeometry::setPhaseY):
+        (WebCore::BackgroundImageGeometry::setHasNonLocalGeometry):
+        (WebCore::BackgroundImageGeometry::hasNonLocalGeometry):
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::BackgroundImageGeometry): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::destOrigin): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setDestOrigin): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::destRect): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setDestRect): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::phase): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setPhase): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::tileSize): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setTileSize): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::spaceSize): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setSpaceSize): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setPhaseX): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setPhaseY): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setHasNonLocalGeometry): Deleted.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::hasNonLocalGeometry): Deleted.
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::RenderLayer):
+        (WebCore::RenderLayer::~RenderLayer):
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerMaskImageInfo.cpp: Added.
+        (WebCore::RenderLayer::MaskImageInfo::layerToMaskMap): Returns a static map that links MaskImageInfo objects to RenderLayers.
+        (WebCore::RenderLayer::MaskImageInfo::getIfExists): Returns the MaskImageInfo associated with a specific RenderLayer.
+        (WebCore::RenderLayer::MaskImageInfo::get): Returns the MaskImageInfo associated with a specific RenderLayer (creates it if necessary).
+        (WebCore::RenderLayer::MaskImageInfo::remove): Removes the MaskImageInfo associated with a specific RenderLayer.
+        (WebCore::RenderLayer::MaskImageInfo::MaskImageInfo):
+        (WebCore::RenderLayer::MaskImageInfo::~MaskImageInfo):
+        (WebCore::RenderLayer::MaskImageInfo::notifyFinished): Gets called when the SVG document finished loading, triggers repaint.
+        (WebCore::RenderLayer::MaskImageInfo::imageChanged): Gets called when the image object changed, triggers repaint.
+        (WebCore::RenderLayer::MaskImageInfo::updateMaskImageClients): Goes through all mask layers and sets image/SVG clients. 
+        Updates list of internal and external SVG references.
+        (WebCore::RenderLayer::MaskImageInfo::removeMaskImageClients): Removes all image/SVG clients and clears lists of internal and external SVG references.
+        * rendering/RenderLayerMaskImageInfo.h: Added.
+        * rendering/RenderObject.h:
+        (WebCore::RenderObject::isRenderSVGResourceMasker):
+        * rendering/style/FillLayer.cpp:
+        (WebCore::FillLayer::FillLayer):
+        (WebCore::FillLayer::operator=):
+        (WebCore::FillLayer::operator==):
+        (WebCore::FillLayer::cullEmptyLayers):
+        (WebCore::FillLayer::hasNonEmptyMaskImage):
+        (WebCore::FillLayer::imagesAreLoaded):
+        * rendering/style/FillLayer.h:
+        (WebCore::FillLayer::maskImage):
+        (WebCore::FillLayer::imageOrMaskImage):
+        (WebCore::FillLayer::setMaskImage):
+        (WebCore::FillLayer::clearMaskImage):
+        (WebCore::FillLayer::hasMaskImage):
+        * rendering/svg/RenderSVGResourceMasker.cpp:
+        (WebCore::RenderSVGResourceMasker::applySVGMask):
+        (WebCore::RenderSVGResourceMasker::applyResource):
+        (WebCore::RenderSVGResourceMasker::drawMaskForRenderer):
+        * rendering/svg/RenderSVGResourceMasker.h:
+        * svg/SVGMaskElement.cpp:
+        (WebCore::SVGMaskElement::createElementRenderer):
+        (WebCore::SVGMaskElement::addClientRenderLayer):
+        (WebCore::SVGMaskElement::removeClientRenderLayer):
+        * svg/SVGMaskElement.h:
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::setCachedDocument):
+        * svg/graphics/SVGImage.cpp:
+        (WebCore::SVGImage::dataChanged):
+
 2014-12-04  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r176789.
index 41527a0..842eb14 100644 (file)
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="..\css\WebKitCSSResourceValue.cpp" />
     <ClCompile Include="..\DerivedSources.cpp">
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
       </PrecompiledHeader>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="..\platform\graphics\MaskImageOperation.cpp" />
     <ClCompile Include="..\platform\graphics\OpenGLShims.cpp" />
     <ClCompile Include="..\platform\graphics\opengl\Extensions3DOpenGL.cpp" />
     <ClCompile Include="..\platform\graphics\opengl\Extensions3DOpenGLCommon.cpp" />
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Production|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="..\rendering\RenderLayerMaskImageInfo.cpp" />
     <ClCompile Include="..\rendering\style\StyleCachedImageSet.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugSuffix|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='DebugSuffix|x64'">true</ExcludedFromBuild>
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\JSVTTRegionList.h" />
     <ClInclude Include="..\accessibility\AccessibilityNodeObject.h" />
     <ClInclude Include="..\css\CSSImageSetValue.h" />
+    <ClInclude Include="..\css\WebKitCSSResourceValue.h" />
     <ClInclude Include="..\ForwardingHeaders\bindings\ScriptFunctionCall.h" />
     <ClInclude Include="..\ForwardingHeaders\bindings\ScriptObject.h" />
     <ClInclude Include="..\ForwardingHeaders\bindings\ScriptValue.h" />
     <ClInclude Include="..\platform\graphics\gstreamer\VideoSinkGStreamer.h" />
     <ClInclude Include="..\platform\graphics\gstreamer\VideoTrackPrivateGStreamer.h" />
     <ClInclude Include="..\platform\graphics\gstreamer\WebKitWebSourceGStreamer.h" />
+    <ClInclude Include="..\platform\graphics\MaskImageOperation.h" />
     <ClInclude Include="..\platform\graphics\MediaPlayerPrivate.h" />
     <ClInclude Include="..\platform\graphics\OpenGLShims.h" />
     <ClInclude Include="..\platform\graphics\opengl\Extensions3DOpenGL.h" />
     <ClInclude Include="..\platform\win\WebCoreBundleWin.h" />
     <ClInclude Include="..\platform\win\WebCoreInstanceHandle.h" />
     <ClInclude Include="..\rendering\HitTestLocation.h" />
+    <ClInclude Include="..\rendering\RenderLayerMaskImageInfo.h" />
     <ClInclude Include="..\rendering\style\StyleCachedImageSet.h" />
     <ClInclude Include="..\storage\StorageStrategy.h" />
     <ClInclude Include="..\svg\graphics\SVGImageForContainer.h" />
index 8c5a3fa..9dd2492 100644 (file)
     <ClCompile Include="..\editing\win\EditorWin.cpp">
       <Filter>editing</Filter>
     </ClCompile>
+    <ClCompile Include="..\platform\graphics\MaskImageOperation.cpp">
+      <Filter>platform\graphics</Filter>
+    </ClCompile>
+    <ClCompile Include="..\rendering\RenderLayerMaskImageInfo.cpp">
+      <Filter>rendering</Filter>
+    </ClCompile>
+    <ClCompile Include="..\css\WebKitCSSResourceValue.cpp">
+      <Filter>css</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\Modules\geolocation\Coordinates.h">
     <ClInclude Include="..\platform\graphics\avfoundation\MediaTimeAVFoundation.h">
       <Filter>platform\graphics\avfoundation</Filter>
     </ClInclude>
+        <ClInclude Include="..\platform\graphics\MaskImageOperation.h">
+      <Filter>platform\graphics</Filter>
+    </ClInclude>
+    <ClInclude Include="..\rendering\RenderLayerMaskImageInfo.h">
+      <Filter>rendering</Filter>
+    </ClInclude>
+    <ClInclude Include="..\css\WebKitCSSResourceValue.h">
+      <Filter>css</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\css\CSSGrammar.y.in">
index caf44b3..e38c340 100644 (file)
                65FD466619B596F6001E2B4D /* WebVideoFullscreenModelVideoElement.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6586FE3D19B548BD005C3C82 /* WebVideoFullscreenModelVideoElement.mm */; };
                65FEA86909833ADE00BED4AB /* Page.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65FEA86809833ADE00BED4AB /* Page.cpp */; };
                6B3480940EEF50D400AC1B41 /* NativeImagePtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B3480920EEF50D400AC1B41 /* NativeImagePtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               6C568CB019DAFEA000430CA2 /* MaskImageOperation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6C568CAE19DAFEA000430CA2 /* MaskImageOperation.cpp */; };
+               6C568CB119DAFEA000430CA2 /* MaskImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C568CAF19DAFEA000430CA2 /* MaskImageOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                6C638895A96CCEE50C8C946C /* CachedResourceRequestInitiators.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C638893A96CCEE50C8C946C /* CachedResourceRequestInitiators.h */; settings = {ATTRIBUTES = (Private, ); }; };
                6C638896A96CCEE50C8C946C /* CachedResourceRequestInitiators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6C638894A96CCEE50C8C946C /* CachedResourceRequestInitiators.cpp */; };
+               6C6CCAB019DC42B90043D5DB /* WebKitCSSResourceValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6C6CCAAE19DC42B90043D5DB /* WebKitCSSResourceValue.cpp */; };
+               6C6CCAB119DC42B90043D5DB /* WebKitCSSResourceValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C6CCAAF19DC42B90043D5DB /* WebKitCSSResourceValue.h */; };
+               6CBFE4A419EBF2D400CA2F9D /* RenderLayerMaskImageInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6CBFE4A219EBF2D400CA2F9D /* RenderLayerMaskImageInfo.cpp */; };
+               6CBFE4A519EBF2D400CA2F9D /* RenderLayerMaskImageInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CBFE4A319EBF2D400CA2F9D /* RenderLayerMaskImageInfo.h */; };
                6CDDE8D01770BB220016E072 /* RegionOversetState.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C70A81417707C49009A446E /* RegionOversetState.h */; settings = {ATTRIBUTES = (Private, ); }; };
                6E0E569B183BFFE600E0E8D5 /* FloatRoundedRect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E0E5699183BFFE600E0E8D5 /* FloatRoundedRect.cpp */; };
                6E0E569C183BFFE600E0E8D5 /* FloatRoundedRect.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E0E569A183BFFE600E0E8D5 /* FloatRoundedRect.h */; settings = {ATTRIBUTES = (Private, ); }; };
                65F80697054D9F86008BF776 /* BlockExceptions.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BlockExceptions.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                65FEA86809833ADE00BED4AB /* Page.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Page.cpp; sourceTree = "<group>"; };
                6B3480920EEF50D400AC1B41 /* NativeImagePtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NativeImagePtr.h; sourceTree = "<group>"; };
+               6C568CAE19DAFEA000430CA2 /* MaskImageOperation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MaskImageOperation.cpp; sourceTree = "<group>"; };
+               6C568CAF19DAFEA000430CA2 /* MaskImageOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MaskImageOperation.h; sourceTree = "<group>"; };
                6C638893A96CCEE50C8C946C /* CachedResourceRequestInitiators.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CachedResourceRequestInitiators.h; sourceTree = "<group>"; };
                6C638894A96CCEE50C8C946C /* CachedResourceRequestInitiators.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CachedResourceRequestInitiators.cpp; sourceTree = "<group>"; };
+               6C6CCAAE19DC42B90043D5DB /* WebKitCSSResourceValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitCSSResourceValue.cpp; sourceTree = "<group>"; };
+               6C6CCAAF19DC42B90043D5DB /* WebKitCSSResourceValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitCSSResourceValue.h; sourceTree = "<group>"; };
                6C70A81417707C49009A446E /* RegionOversetState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegionOversetState.h; sourceTree = "<group>"; };
+               6CBFE4A219EBF2D400CA2F9D /* RenderLayerMaskImageInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderLayerMaskImageInfo.cpp; sourceTree = "<group>"; };
+               6CBFE4A319EBF2D400CA2F9D /* RenderLayerMaskImageInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderLayerMaskImageInfo.h; sourceTree = "<group>"; };
                6E0E5699183BFFE600E0E8D5 /* FloatRoundedRect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatRoundedRect.cpp; sourceTree = "<group>"; };
                6E0E569A183BFFE600E0E8D5 /* FloatRoundedRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatRoundedRect.h; sourceTree = "<group>"; };
                6E21C6BF1126338500A7BE02 /* GraphicsContext3D.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3D.cpp; sourceTree = "<group>"; };
                                141DC04C164834B900371E5A /* LayoutRect.cpp */,
                                141DC04D164834B900371E5A /* LayoutRect.h */,
                                141DC04E164834B900371E5A /* LayoutSize.h */,
+                               6C568CAE19DAFEA000430CA2 /* MaskImageOperation.cpp */,
+                               6C568CAF19DAFEA000430CA2 /* MaskImageOperation.h */,
                                E4B41E0C0CBF90BD00AF2ECE /* MediaPlayer.cpp */,
                                E4B41E0D0CBF90BD00AF2ECE /* MediaPlayer.h */,
                                079F5E4B0F3BEBEA005E0782 /* MediaPlayerPrivate.h */,
                                3106036C14327D2E00ABF4BA /* WebKitCSSFilterValue.cpp */,
                                3106036D14327D2E00ABF4BA /* WebKitCSSFilterValue.h */,
                                3106036E14327D2E00ABF4BA /* WebKitCSSFilterValue.idl */,
+                               6C6CCAAE19DC42B90043D5DB /* WebKitCSSResourceValue.cpp */,
+                               6C6CCAAF19DC42B90043D5DB /* WebKitCSSResourceValue.h */,
                                31288E6E0E3005D6003619AE /* CSSKeyframeRule.cpp */,
                                31288E6F0E3005D6003619AE /* CSSKeyframeRule.h */,
                                316FE0910E6CCD7F00BF6088 /* CSSKeyframeRule.idl */,
                                0F580CF90F12DE9B0051D689 /* RenderLayerCompositor.h */,
                                50D10D971545F5760096D288 /* RenderLayerFilterInfo.cpp */,
                                50D10D981545F5760096D288 /* RenderLayerFilterInfo.h */,
+                               6CBFE4A219EBF2D400CA2F9D /* RenderLayerMaskImageInfo.cpp */,
+                               6CBFE4A319EBF2D400CA2F9D /* RenderLayerMaskImageInfo.h */,
                                3C244FE5A375AC633F88BE6F /* RenderLayerModelObject.cpp */,
                                3C244FE4A375AC633F88BE6F /* RenderLayerModelObject.h */,
                                BC33FB1A0F30EE85002CDD7C /* RenderLineBoxList.cpp */,
                                316FE1140E6E1DA700BF6088 /* AnimationController.h in Headers */,
                                0F15DA8A0F3AAEE70000CE47 /* AnimationControllerPrivate.h in Headers */,
                                49E912AD0EFAC906009D0CAF /* AnimationList.h in Headers */,
+                               6C568CB119DAFEA000430CA2 /* MaskImageOperation.h in Headers */,
                                0F580FAF149800D400FB5BD8 /* AnimationUtilities.h in Headers */,
                                93309DD7099E64920056E581 /* AppendNodeCommand.h in Headers */,
                                1A8F6BBD0DB55CDC001DB794 /* ApplicationCache.h in Headers */,
                                CDBEAEAD19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h in Headers */,
                                070E09191875EEFC003A1D3C /* MediaSession.h in Headers */,
                                07F944161864D046005D31CB /* MediaSessionManager.h in Headers */,
+                               6CBFE4A519EBF2D400CA2F9D /* RenderLayerMaskImageInfo.h in Headers */,
                                07638A991884487200E15A1B /* MediaSessionManagerIOS.h in Headers */,
                                CD3A495F17A9D01B00274E42 /* MediaSource.h in Headers */,
                                CD641EB31818F5ED00EE4C41 /* MediaSourcePrivate.h in Headers */,
                                CDCFABBD18C0AF78006F8450 /* SelectionSubtreeRoot.h in Headers */,
                                E44B4BB4141650D7002B1D8B /* SelectorChecker.h in Headers */,
                                432D3FE818A8658400D7DC03 /* SelectorCheckerTestFunctions.h in Headers */,
+                               6C6CCAB119DC42B90043D5DB /* WebKitCSSResourceValue.h in Headers */,
                                26B999971804D54200D01121 /* SelectorCompiler.h in Headers */,
                                415071581685067300C3C7B3 /* SelectorFilter.h in Headers */,
                                43107BE218CC19DE00CC18E8 /* SelectorPseudoTypeMap.h in Headers */,
                                8A195933147EA16E00D1EA61 /* DOMWebKitNamedFlow.mm in Sources */,
                                31C0FF4D0E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.mm in Sources */,
                                85C7F5E80AAFBAFB004014DD /* DOMWheelEvent.mm in Sources */,
+                               6C6CCAB019DC42B90043D5DB /* WebKitCSSResourceValue.cpp in Sources */,
                                1403B99809EB13AF00797C7F /* DOMWindow.cpp in Sources */,
                                FD677738195CAF3D0072E0D3 /* DOMWindowCSS.cpp in Sources */,
                                517FBA1E151AB17C00B57959 /* DOMWindowExtension.cpp in Sources */,
                                CDB859F7160D48A400E5B07F /* MediaKeyEvent.cpp in Sources */,
                                CDA98DD816025BEF00FEA3B1 /* MediaKeyMessageEvent.cpp in Sources */,
                                CD1B4A65160786AE00282DF9 /* MediaKeyNeededEvent.cpp in Sources */,
+                               6C568CB019DAFEA000430CA2 /* MaskImageOperation.cpp in Sources */,
                                CDA98E0D1603FE4A00FEA3B1 /* MediaKeys.cpp in Sources */,
                                CDA98E0E1603FE5800FEA3B1 /* MediaKeySession.cpp in Sources */,
                                A8EA80090A19516E00A8EF5F /* MediaList.cpp in Sources */,
                                F55B3DC51251F12D003EF269 /* MonthInputType.cpp in Sources */,
                                85031B450A44EFC700F992E0 /* MouseEvent.cpp in Sources */,
                                93EB355F09E37FD600F43799 /* MouseEventWithHitTestResults.cpp in Sources */,
+                               6CBFE4A419EBF2D400CA2F9D /* RenderLayerMaskImageInfo.cpp in Sources */,
                                85031B470A44EFC700F992E0 /* MouseRelatedEvent.cpp in Sources */,
                                93309DFB099E64920056E581 /* MoveSelectionCommand.cpp in Sources */,
                                FDB1700514A2BAB200A2B5D9 /* MultiChannelResampler.cpp in Sources */,
index d029ec1..a6c3ce6 100644 (file)
@@ -54,6 +54,7 @@
 #include "SVGColor.h"
 #include "SVGPaint.h"
 #include "WebKitCSSFilterValue.h"
+#include "WebKitCSSResourceValue.h"
 #include "WebKitCSSTransformValue.h"
 
 #if ENABLE(CSS_GRID_LAYOUT)
@@ -311,6 +312,8 @@ String CSSValue::cssText() const
         return downcast<SVGColor>(*this).customCSSText();
     case SVGPaintClass:
         return downcast<SVGPaint>(*this).customCSSText();
+    case WebKitCSSResourceClass:
+        return downcast<WebKitCSSResourceValue>(*this).customCSSText();
     }
     ASSERT_NOT_REACHED();
     return String();
@@ -423,6 +426,9 @@ void CSSValue::destroy()
     case SVGPaintClass:
         delete downcast<SVGPaint>(this);
         return;
+    case WebKitCSSResourceClass:
+        delete downcast<WebKitCSSResourceValue>(this);
+        return;
     }
     ASSERT_NOT_REACHED();
 }
index 01ee62a..36c2994 100644 (file)
@@ -103,6 +103,7 @@ public:
     bool isSVGColor() const { return m_classType == SVGColorClass || m_classType == SVGPaintClass; }
     bool isSVGPaint() const { return m_classType == SVGPaintClass; }
     bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; }
+    bool isWebKitCSSResourceValue() const { return m_classType == WebKitCSSResourceClass; }
 
     bool isCSSOMSafe() const { return m_isCSSOMSafe; }
     bool isSubtypeExposedToCSSOM() const
@@ -173,6 +174,8 @@ protected:
 #if ENABLE(CSS_GRID_LAYOUT)
         GridLineNamesClass,
 #endif
+        WebKitCSSResourceClass
+
         // Do not append non-list class types here.
     };
 
index c024158..1f0ba01 100644 (file)
 #include "VisitedLinkState.h"
 #include "WebKitCSSFilterValue.h"
 #include "WebKitCSSRegionRule.h"
+#include "WebKitCSSResourceValue.h"
 #include "WebKitCSSTransformValue.h"
 #include "WebKitFontFamilyNames.h"
 #include "XMLNames.h"
@@ -236,6 +237,7 @@ inline void StyleResolver::State::clear()
     m_regionForStyling = nullptr;
     m_pendingImageProperties.clear();
     m_filtersWithPendingSVGDocuments.clear();
+    m_maskImagesWithPendingSVGDocuments.clear();
     m_cssToLengthConversionData = CSSToLengthConversionData();
 }
 
@@ -3459,6 +3461,51 @@ bool StyleResolver::createFilterOperations(CSSValue* inValue, FilterOperations&
     return true;
 }
 
+bool StyleResolver::createMaskImageOperations(CSSValue* inValue, Vector<RefPtr<MaskImageOperation>>& outOperations)
+{
+    ASSERT(outOperations.isEmpty());
+    if (!inValue)
+        return false;
+
+    ASSERT(is<CSSValueList>(*inValue));
+
+    for (auto& currValue : downcast<CSSValueList>(*inValue)) {
+        if (!is<WebKitCSSResourceValue>(currValue.get()))
+            continue;
+        
+        WebKitCSSResourceValue& maskImageValue = downcast<WebKitCSSResourceValue>(currValue.get());
+        RefPtr<CSSValue> maskInnerValue = maskImageValue.innerValue();
+        RefPtr<MaskImageOperation> newMaskImage;
+        
+        if (is<CSSPrimitiveValue>(maskInnerValue.get())) {
+            RefPtr<CSSPrimitiveValue> primitiveValue = downcast<CSSPrimitiveValue>(maskInnerValue.get());
+            if (primitiveValue->isValueID() && primitiveValue->getValueID() == CSSValueNone)
+                newMaskImage = MaskImageOperation::create();
+            else {
+                String cssUrl = primitiveValue->getStringValue();
+                URL url = m_state.document().completeURL(cssUrl);
+                
+                bool isExternalDocument = (SVGURIReference::isExternalURIReference(cssUrl, m_state.document()));
+                newMaskImage = MaskImageOperation::create(&maskImageValue, cssUrl, url.fragmentIdentifier(), isExternalDocument, m_state.document().cachedResourceLoader());
+                if (isExternalDocument)
+                    m_state.maskImagesWithPendingSVGDocuments().append(newMaskImage);
+            }
+        } else {
+            RefPtr<StyleImage> image = styleImage(CSSPropertyWebkitMaskImage, *maskInnerValue);
+            if (image.get())
+                newMaskImage = MaskImageOperation::create(image);
+        }
+
+        // If we didn't get a valid value, use None so we keep the correct number and order of masks.
+        if (!newMaskImage.get())
+            newMaskImage = MaskImageOperation::create();
+
+        outOperations.append(newMaskImage);
+    }
+
+    return true;
+}
+
 PassRefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage, const ResourceLoaderOptions& options)
 {
     if (auto imageValue = pendingImage.cssImageValue())
index 55ca0f6..e5867f0 100644 (file)
@@ -28,6 +28,7 @@
 #include "DocumentRuleSets.h"
 #include "InspectorCSSOMWrappers.h"
 #include "LinkHash.h"
+#include "MaskImageOperation.h"
 #include "MediaQueryExp.h"
 #include "RenderStyle.h"
 #include "RuleFeature.h"
@@ -237,6 +238,7 @@ public:
     void clearCachedPropertiesAffectedByViewportUnits();
 
     bool createFilterOperations(CSSValue* inValue, FilterOperations& outOperations);
+    bool createMaskImageOperations(CSSValue* inValue, Vector<RefPtr<MaskImageOperation>>& outOperations);
     void loadPendingSVGDocuments();
 
     void loadPendingResources();
@@ -380,6 +382,7 @@ public:
         PendingImagePropertyMap& pendingImageProperties() { return m_pendingImageProperties; }
 
         Vector<RefPtr<ReferenceFilterOperation>>& filtersWithPendingSVGDocuments() { return m_filtersWithPendingSVGDocuments; }
+        Vector<RefPtr<MaskImageOperation>>& maskImagesWithPendingSVGDocuments() { return m_maskImagesWithPendingSVGDocuments; }
 
         void setLineHeightValue(CSSValue* value) { m_lineHeightValue = value; }
         CSSValue* lineHeightValue() { return m_lineHeightValue; }
@@ -428,6 +431,7 @@ public:
         PendingImagePropertyMap m_pendingImageProperties;
 
         Vector<RefPtr<ReferenceFilterOperation>> m_filtersWithPendingSVGDocuments;
+        Vector<RefPtr<MaskImageOperation>> m_maskImagesWithPendingSVGDocuments;
 
         CSSValue* m_lineHeightValue;
         bool m_fontDirty;
diff --git a/Source/WebCore/css/WebKitCSSResourceValue.cpp b/Source/WebCore/css/WebKitCSSResourceValue.cpp
new file mode 100644 (file)
index 0000000..480b291
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebKitCSSResourceValue.h"
+
+#include "CSSParser.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSValueList.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+WebKitCSSResourceValue::WebKitCSSResourceValue(PassRefPtr<CSSValue> resourceValue)
+    : CSSValue(WebKitCSSResourceClass)
+    , m_innerValue(resourceValue)
+{
+}
+
+String WebKitCSSResourceValue::customCSSText() const
+{
+    if (isCSSValueNone())
+        return "none";
+
+    if (m_innerValue.get()) {
+        if (is<CSSPrimitiveValue>(m_innerValue.get()) && downcast<CSSPrimitiveValue>(m_innerValue.get())->isURI()) {
+            StringBuilder result;
+            result.appendLiteral("url(");
+            result.append(quoteCSSURLIfNeeded(downcast<CSSPrimitiveValue>(m_innerValue.get())->getStringValue()));
+            result.appendLiteral(")");
+            return result.toString();
+        }
+        
+        return m_innerValue->cssText();
+    }
+    
+    return "";
+}
+
+bool WebKitCSSResourceValue::isCSSValueNone() const
+{
+    if (is<CSSPrimitiveValue>(m_innerValue.get())) {
+        RefPtr<CSSPrimitiveValue> primitiveValue = downcast<CSSPrimitiveValue>(m_innerValue.get());
+        return (primitiveValue->isValueID() && primitiveValue->getValueID() == CSSValueNone);
+    }
+
+    return false;
+}
+
+}
diff --git a/Source/WebCore/css/WebKitCSSResourceValue.h b/Source/WebCore/css/WebKitCSSResourceValue.h
new file mode 100644 (file)
index 0000000..4577c49
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef WebKitCSSResourceValue_h
+#define WebKitCSSResourceValue_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class WebKitCSSResourceValue : public CSSValue {
+public:
+    static PassRef<WebKitCSSResourceValue> create(PassRefPtr<CSSValue> resourceValue)
+    {
+        return adoptRef(*new WebKitCSSResourceValue(resourceValue));
+    }
+
+    String customCSSText() const;
+    PassRefPtr<CSSValue> innerValue() { return m_innerValue; };
+    bool isCSSValueNone() const;
+private:
+    WebKitCSSResourceValue(PassRefPtr<CSSValue> resourceValue);
+    RefPtr<CSSValue> m_innerValue;
+};
+
+}
+
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(WebKitCSSResourceValue, isWebKitCSSResourceValue())
+
+#endif // WebKitCSSResourceValue_h
index ec832d5..37fa99c 100644 (file)
@@ -756,6 +756,14 @@ void CachedResourceLoader::removeCachedResource(CachedResource* resource) const
     m_documentResources.remove(resource->url());
 }
 
+void CachedResourceLoader::addCachedResource(CachedResource* resource)
+{
+    m_documentResources.set(resource->url(), resource);
+
+    if (!memoryCache().add(resource))
+        resource->setOwningCachedResourceLoader(this);
+}
+
 void CachedResourceLoader::loadDone(CachedResource* resource, bool shouldPerformPostLoadActions)
 {
     RefPtr<DocumentLoader> protectDocumentLoader(m_documentLoader);
index 7958e62..3c0ea55 100644 (file)
@@ -114,6 +114,7 @@ public:
     SessionID sessionID() const;
 
     void removeCachedResource(CachedResource*) const;
+    void addCachedResource(CachedResource*);
 
     void loadDone(CachedResource*, bool shouldPerformPostLoadActions = true);
 
index a523020..33e07e8 100644 (file)
 #include "config.h"
 #include "CachedSVGDocument.h"
 
+#include "DocumentLoader.h"
+#include "EmptyClients.h"
+#include "FrameView.h"
+#include "MainFrame.h"
+#include "Page.h"
+#include "PageConfiguration.h"
+#include "Settings.h"
 #include "SharedBuffer.h"
 
 namespace WebCore {
@@ -30,6 +37,8 @@ namespace WebCore {
 CachedSVGDocument::CachedSVGDocument(const ResourceRequest& request, SessionID sessionID)
     : CachedResource(request, SVGDocumentResource, sessionID)
     , m_decoder(TextResourceDecoder::create("application/xml"))
+    , m_shouldCreateFrameForDocument(true)
+    , m_canReuseResource(true)
 {
     setAccept("image/svg+xml");
 }
@@ -51,9 +60,17 @@ String CachedSVGDocument::encoding() const
 void CachedSVGDocument::finishLoading(SharedBuffer* data)
 {
     if (data) {
-        // We don't need to create a new frame because the new document belongs to the parent UseElement.
-        m_document = SVGDocument::create(nullptr, response().url());
-        m_document->setContent(m_decoder->decodeAndFlush(data->data(), data->size()));
+        // In certain situations (like the scenario when this document belongs to an UseElement) we don't need to create a frame.
+        if (m_shouldCreateFrameForDocument) {
+            PageConfiguration pageConfiguration;
+            fillWithEmptyClients(pageConfiguration);
+            
+            m_page = Page::createPageFromBuffer(pageConfiguration, data, "image/svg+xml", false, true);
+            m_document = downcast<SVGDocument>(m_page->mainFrame().document());
+        } else {
+            m_document = SVGDocument::create(nullptr, response().url());
+            m_document->setContent(m_decoder->decodeAndFlush(data->data(), data->size()));
+        }
     }
     CachedResource::finishLoading(data);
 }
index a791cd8..72b7864 100644 (file)
@@ -36,6 +36,9 @@ public:
     virtual ~CachedSVGDocument();
 
     SVGDocument* document() const { return m_document.get(); }
+    void setShouldCreateFrameForDocument(bool shouldCreate) { m_shouldCreateFrameForDocument = shouldCreate; }
+    virtual bool canReuse(const ResourceRequest&) const override { return m_canReuseResource; }
+    void setCanReuse(bool canReuseResource) { m_canReuseResource = canReuseResource; };
 
 private:
     virtual bool mayTryReplaceEncodedData() const override { return true; }
@@ -45,6 +48,9 @@ private:
 
     RefPtr<SVGDocument> m_document;
     RefPtr<TextResourceDecoder> m_decoder;
+    std::unique_ptr<Page> m_page;
+    bool m_shouldCreateFrameForDocument;
+    bool m_canReuseResource;
 };
 
 } // namespace WebCore
index 06f3ab8..b6b4626 100644 (file)
 
 namespace WebCore {
 
-CachedSVGDocumentReference::CachedSVGDocumentReference(const String& url)
+CachedSVGDocumentReference::CachedSVGDocumentReference(const String& url, CachedSVGDocumentClient* additionalDocumentClient, bool canReuseResource)
     : m_url(url)
     , m_document(0)
     , m_loadRequested(false)
+    , m_additionalDocumentClient(additionalDocumentClient)
+    , m_canReuseResource(canReuseResource)
 {
 }
 
 CachedSVGDocumentReference::~CachedSVGDocumentReference()
 {
-    if (m_document)
+    if (m_document) {
         m_document->removeClient(this);
+        
+        if (m_additionalDocumentClient)
+            m_document->removeClient(m_additionalDocumentClient);
+    }
 }
 
 void CachedSVGDocumentReference::load(CachedResourceLoader* loader)
@@ -56,8 +62,13 @@ void CachedSVGDocumentReference::load(CachedResourceLoader* loader)
     CachedResourceRequest request(ResourceRequest(loader->document()->completeURL(m_url)));
     request.setInitiator(cachedResourceRequestInitiators().css);
     m_document = loader->requestSVGDocument(request);
-    if (m_document)
+    if (m_document) {
+        m_document->setCanReuse(m_canReuseResource);
         m_document->addClient(this);
+        
+        if (m_additionalDocumentClient)
+            m_document->addClient(m_additionalDocumentClient);
+    }
 
     m_loadRequested = true;
 }
index 5da3eec..41f41db 100644 (file)
@@ -37,7 +37,7 @@ class CachedResourceLoader;
 
 class CachedSVGDocumentReference : public CachedSVGDocumentClient {
 public:
-    CachedSVGDocumentReference(const String&);
+    CachedSVGDocumentReference(const String& url, CachedSVGDocumentClient* additionalDocumentClient = nullptr, bool canReuseResource = true);
 
     virtual ~CachedSVGDocumentReference();
 
@@ -50,6 +50,8 @@ private:
     String m_url;
     CachedResourceHandle<CachedSVGDocument> m_document;
     bool m_loadRequested;
+    CachedSVGDocumentClient* m_additionalDocumentClient;
+    bool m_canReuseResource;
 };
 
 };
index 834e9e8..1064014 100644 (file)
@@ -4382,6 +4382,14 @@ bool FrameView::isFlippedDocument() const
     return renderView->style().isFlippedBlocksWritingMode();
 }
 
+bool FrameView::containsSVGDocument() const
+{
+    if (frame().document())
+        return frame().document()->isSVGDocument();
+    
+    return false;
+}
+
 void FrameView::notifyWidgetsInAllFrames(WidgetNotification notification)
 {
     for (Frame* frame = m_frame.get(); frame; frame = frame->tree().traverseNext(m_frame.get())) {
index f5b5e5d..97ab39d 100644 (file)
@@ -526,6 +526,7 @@ protected:
 
     virtual bool isVerticalDocument() const override;
     virtual bool isFlippedDocument() const override;
+    virtual bool containsSVGDocument() const override;
 
 private:
     explicit FrameView(Frame&);
index 1520376..b2406dc 100644 (file)
@@ -29,6 +29,7 @@
 #include "ClientRectList.h"
 #include "ContextMenuClient.h"
 #include "ContextMenuController.h"
+#include "DocumentLoader.h"
 #include "DocumentMarkerController.h"
 #include "DocumentStyleSheetCollection.h"
 #include "DragController.h"
@@ -275,6 +276,33 @@ Page::~Page()
     m_visitedLinkStore->removePage(*this);
 }
 
+std::unique_ptr<Page> Page::createPageFromBuffer(PageConfiguration& pageConfiguration, const SharedBuffer* buffer, const String& mimeType, bool canHaveScrollbars, bool transparent)
+{
+    ASSERT(buffer);
+    
+    std::unique_ptr<Page> newPage = std::make_unique<Page>(pageConfiguration);
+    newPage->settings().setMediaEnabled(false);
+    newPage->settings().setScriptEnabled(false);
+    newPage->settings().setPluginsEnabled(false);
+    
+    Frame& frame = newPage->mainFrame();
+    frame.setView(FrameView::create(frame));
+    frame.init();
+    FrameLoader& loader = frame.loader();
+    loader.forceSandboxFlags(SandboxAll);
+    
+    frame.view()->setCanHaveScrollbars(canHaveScrollbars);
+    frame.view()->setTransparent(transparent);
+    
+    ASSERT(loader.activeDocumentLoader()); // DocumentLoader should have been created by frame->init().
+    loader.activeDocumentLoader()->writer().setMIMEType(mimeType);
+    loader.activeDocumentLoader()->writer().begin(URL()); // create the empty document
+    loader.activeDocumentLoader()->writer().addData(buffer->data(), buffer->size());
+    loader.activeDocumentLoader()->writer().end();
+    
+    return newPage;
+}
+
 void Page::clearPreviousItemFromAllPages(HistoryItem* item)
 {
     if (!allPages)
index 65bd862..9acc489 100644 (file)
@@ -107,6 +107,7 @@ class ViewStateChangeObserver;
 class VisitedLinkStore;
 
 typedef uint64_t LinkHash;
+class SharedBuffer;
 
 enum FindDirection { FindDirectionForward, FindDirectionBackward };
 
@@ -124,6 +125,8 @@ public:
     WEBCORE_EXPORT ~Page();
 
     WEBCORE_EXPORT uint64_t renderTreeSize() const;
+    
+    static std::unique_ptr<Page> createPageFromBuffer(PageConfiguration&, const SharedBuffer*, const String& mimeType, bool canHaveScrollbars, bool transparent);
 
     void setNeedsRecalcStyleInAllFrames();
 
index f2ef591..4846bde 100644 (file)
@@ -410,6 +410,7 @@ protected:
     // Subclassed by FrameView to check the writing-mode of the document.
     virtual bool isVerticalDocument() const { return true; }
     virtual bool isFlippedDocument() const { return false; }
+    virtual bool containsSVGDocument() const { return false; }
 
     // Called to update the scrollbars to accurately reflect the state of the view.
     void updateScrollbars(const IntSize& desiredOffset);
diff --git a/Source/WebCore/platform/graphics/MaskImageOperation.cpp b/Source/WebCore/platform/graphics/MaskImageOperation.cpp
new file mode 100644 (file)
index 0000000..67af85c
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MaskImageOperation.h"
+
+#include "CachedImage.h"
+#include "CachedSVGDocument.h"
+#include "RenderBoxModelObject.h"
+#include "RenderSVGResourceMasker.h"
+#include "SVGDocument.h"
+#include "SVGMaskElement.h"
+#include "SVGSVGElement.h"
+#include "StyleCachedImage.h"
+#include "SubresourceLoader.h"
+#include "WebKitCSSResourceValue.h"
+
+namespace WebCore {
+
+PassRefPtr<MaskImageOperation> MaskImageOperation::create(PassRefPtr<WebKitCSSResourceValue> cssValue, const String& url, const String& fragment, bool isExternalDocument, PassRefPtr<CachedResourceLoader> cachedResourceLoader)
+{
+    return adoptRef(new MaskImageOperation(cssValue, url, fragment, isExternalDocument, cachedResourceLoader));
+}
+
+PassRefPtr<MaskImageOperation> MaskImageOperation::create(PassRefPtr<StyleImage> generatedImage)
+{
+    return adoptRef(new MaskImageOperation(generatedImage));
+}
+
+PassRefPtr<MaskImageOperation> MaskImageOperation::create()
+{
+    return adoptRef(new MaskImageOperation());
+}
+
+MaskImageOperation::MaskImageOperation(PassRefPtr<WebKitCSSResourceValue> cssValue, const String& url, const String& fragment, bool isExternalDocument, PassRefPtr<CachedResourceLoader> cachedResourceLoader)
+    : m_url(url)
+    , m_fragment(fragment)
+    , m_isExternalDocument(isExternalDocument)
+    , m_renderLayerImageClient(nullptr)
+    , m_cssMaskImageValue(cssValue)
+    , m_cachedResourceLoader(cachedResourceLoader)
+{
+    ASSERT(m_cssMaskImageValue.get());
+}
+
+MaskImageOperation::MaskImageOperation(PassRefPtr<StyleImage> generatedImage)
+    : m_isExternalDocument(false)
+    , m_styleImage(generatedImage)
+    , m_renderLayerImageClient(nullptr)
+{
+}
+
+MaskImageOperation::MaskImageOperation()
+    : m_isExternalDocument(false)
+    , m_renderLayerImageClient(nullptr)
+{
+    m_cssMaskImageValue = WebKitCSSResourceValue::create(CSSPrimitiveValue::createIdentifier(CSSValueNone));
+}
+
+MaskImageOperation::~MaskImageOperation()
+{
+}
+
+bool MaskImageOperation::isCSSValueNone() const
+{
+    if (image())
+        return false;
+
+    ASSERT(m_cssMaskImageValue.get());
+    return m_cssMaskImageValue->isCSSValueNone();
+}
+
+PassRefPtr<CSSValue> MaskImageOperation::cssValue()
+{
+    if (image())
+        return image()->cssValue();
+    
+    if (isCSSValueNone())
+        return m_cssMaskImageValue->innerValue();
+
+    ASSERT(m_cssMaskImageValue.get());
+    return m_cssMaskImageValue.get();
+}
+
+bool MaskImageOperation::isMaskLoaded() const
+{
+    if (!m_isExternalDocument)
+        return true;
+
+    if (image())
+        return (image()->cachedImage() && image()->cachedImage()->image());
+    
+    if (m_cachedSVGDocumentReference.get()) {
+        if (CachedSVGDocument* cachedSVGDocument = m_cachedSVGDocumentReference->document())
+            return (cachedSVGDocument->document() != nullptr);
+    }
+    
+    return false;
+}
+
+void MaskImageOperation::setRenderLayerImageClient(CachedImageClient* client)
+{
+    if (m_renderLayerImageClient == client)
+        return;
+
+    if (CachedImage* cachedImage = (image() ? image()->cachedImage() : nullptr)) {
+        if (m_renderLayerImageClient)
+            cachedImage->removeClient(m_renderLayerImageClient);
+        
+        if (client)
+            cachedImage->addClient(client);
+    }
+
+    m_renderLayerImageClient = client;
+}
+
+void MaskImageOperation::addRendererImageClient(RenderElement* client)
+{
+    ASSERT(client);
+
+    if (m_styleImage.get())
+        m_styleImage->addClient(client);
+    
+    m_rendererImageClients.add(client);
+}
+
+void MaskImageOperation::removeRendererImageClient(RenderElement* client)
+{
+    ASSERT(client && m_rendererImageClients.contains(client));
+    
+    if (m_styleImage.get())
+        m_styleImage->removeClient(client);
+    
+    m_rendererImageClients.remove(client);
+}
+
+CachedSVGDocumentReference* MaskImageOperation::ensureCachedSVGDocumentReference()
+{
+    // If we ended up loading the data into an Image, then the SVG document was not valid.
+    if (image())
+        return nullptr;
+
+    if (!m_cachedSVGDocumentReference.get())
+        m_cachedSVGDocumentReference = std::make_unique<CachedSVGDocumentReference>(m_url, this, false);
+    return m_cachedSVGDocumentReference.get();
+}
+
+void MaskImageOperation::notifyFinished(CachedResource* resource)
+{
+    // The only one notifying us should be the SVG document we hold.
+    CachedSVGDocument* cachedSVGDocument = ensureCachedSVGDocumentReference()->document();
+    if ((CachedResource*)cachedSVGDocument != resource || !resource) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+    
+    // Check if we find a valid masking element in this SVG document.
+    SVGDocument* svgDocument = cachedSVGDocument->document();
+    bool validMaskFound = false;
+    if (svgDocument && svgDocument->rootElement()) {
+        // Are we looking for a specific element in the SVG document?
+        if (fragment().length()) {
+            if (Element* maskingElement = svgDocument->rootElement()->getElementById(fragment())) {
+                if (is<SVGMaskElement>(maskingElement))
+                    validMaskFound = true;
+            }
+        }
+    }
+    
+    // If no valid mask was found, this is not a valid SVG document or it specified an invalid fragment identifier.
+    // Fallback to the normal way of loading the document in an Image object.
+    if (!validMaskFound) {
+        // Get the resource loader, acquire the resource buffer and load it into an image.
+        ASSERT(cachedSVGDocument->loader());
+        if (SubresourceLoader* loader = cachedSVGDocument->loader()) {
+            if (SharedBuffer* dataBuffer = loader->resourceData()) {
+                m_styleImage = StyleCachedImage::create(new CachedImage(cachedSVGDocument->resourceRequest(), cachedSVGDocument->sessionID()));
+                if (m_renderLayerImageClient)
+                    m_styleImage->cachedImage()->addClient(m_renderLayerImageClient);
+                for (auto itClient : m_rendererImageClients)
+                    m_styleImage->addClient(itClient.key);
+
+                m_styleImage->cachedImage()->setResponse(cachedSVGDocument->response());
+                m_styleImage->cachedImage()->finishLoading(dataBuffer);
+
+                // Let the cached resource loader of the document which requested this mask keep a handle to this
+                // cached image to ensure it only gets deleted when it should.
+                if (m_cachedResourceLoader.get())
+                    m_cachedResourceLoader->addCachedResource(m_styleImage->cachedImage());
+            }
+            
+            // Destroy the current SVG document as its no longer needed
+            m_cachedSVGDocumentReference = nullptr;
+        }
+    }
+}
+
+bool MaskImageOperation::drawMask(RenderElement& renderer, BackgroundImageGeometry& geometry, GraphicsContext* context, CompositeOperator compositeOp)
+{
+    // This method only handles custom masks.
+    if (image())
+        return false;
+
+    if (RenderSVGResourceMasker* svgMasker = getSVGMasker(renderer)) {
+        svgMasker->drawMaskForRenderer(renderer, geometry, context, compositeOp);
+        return true;
+    }
+
+    return false;
+}
+
+RenderSVGResourceMasker* MaskImageOperation::getSVGMasker(RenderElement& renderer)
+{
+    if (image())
+        return nullptr;
+
+    // Identify the element referenced by the fragmentId.
+    CachedSVGDocumentReference* svgDocumentReference = cachedSVGDocumentReference();
+    Element* elementForMasking = nullptr;
+    RenderObject* svgResourceForMasking = nullptr;
+    if (svgDocumentReference && svgDocumentReference->document()) {
+        SVGDocument* svgDocument = svgDocumentReference->document()->document();
+        if (svgDocument && svgDocument->rootElement())
+            elementForMasking = svgDocument->rootElement()->getElementById(fragment());
+    } else
+        elementForMasking = renderer.document().getElementById(fragment());
+
+    if (elementForMasking)
+        svgResourceForMasking = elementForMasking->renderer();
+
+    // Check if it's the correct type
+    if (svgResourceForMasking && svgResourceForMasking->isSVGResourceContainer() && downcast<RenderSVGResourceContainer>(svgResourceForMasking)->resourceType() == MaskerResourceType)
+        return static_cast<RenderSVGResourceMasker*>(svgResourceForMasking);
+
+    return nullptr;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/MaskImageOperation.h b/Source/WebCore/platform/graphics/MaskImageOperation.h
new file mode 100644 (file)
index 0000000..48753bd
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef MaskImageOperation_h
+#define MaskImageOperation_h
+
+#include "CachedResourceLoader.h"
+#include "CachedSVGDocumentClient.h"
+#include "CachedSVGDocumentReference.h"
+#include "Color.h"
+#include "Image.h"
+#include "LayoutSize.h"
+#include "Length.h"
+#include "StyleImage.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+    
+class BackgroundImageGeometry;
+class CachedImageClient;
+class RenderSVGResourceMasker;
+class WebKitCSSResourceValue;
+
+class MaskImageOperation final : public RefCounted<MaskImageOperation>, public CachedSVGDocumentClient {
+public:
+    static PassRefPtr<MaskImageOperation> create(PassRefPtr<WebKitCSSResourceValue> cssValue, const String& url, const String& fragment, bool isExternalDocument, PassRefPtr<CachedResourceLoader>);
+    static PassRefPtr<MaskImageOperation> create(PassRefPtr<StyleImage> generatedImage);
+    static PassRefPtr<MaskImageOperation> create();
+
+    PassRefPtr<CSSValue> cssValue();
+
+    virtual ~MaskImageOperation();
+
+    const String& url() const { return m_url; }
+    const String& fragment() const { return m_fragment; }
+    StyleImage* image() const { return m_styleImage.get(); }
+    void setImage(PassRefPtr<StyleImage> image) { m_styleImage = image; }
+    void setRenderLayerImageClient(CachedImageClient*);
+    void addRendererImageClient(RenderElement*);
+    void removeRendererImageClient(RenderElement*);
+    bool isMaskLoaded() const;
+    bool drawMask(RenderElement& renderer, BackgroundImageGeometry&, GraphicsContext*, CompositeOperator);
+    bool isCSSValueNone() const;
+
+    CachedSVGDocumentReference* cachedSVGDocumentReference() const { return m_cachedSVGDocumentReference.get(); }
+    CachedSVGDocumentReference* ensureCachedSVGDocumentReference();
+    
+    virtual void notifyFinished(CachedResource*) override;
+
+private:
+    MaskImageOperation(PassRefPtr<WebKitCSSResourceValue> cssValue, const String& url, const String& fragment, bool isExternalDocument, PassRefPtr<CachedResourceLoader>);
+    MaskImageOperation(PassRefPtr<StyleImage> generatedImage);
+    MaskImageOperation();
+
+    RenderSVGResourceMasker* getSVGMasker(RenderElement& renderer);
+
+    String m_url;
+    String m_fragment;
+    bool m_isExternalDocument;
+    std::unique_ptr<CachedSVGDocumentReference> m_cachedSVGDocumentReference;
+    RefPtr<StyleImage> m_styleImage;
+    CachedImageClient* m_renderLayerImageClient;
+    HashCountedSet<RenderElement*> m_rendererImageClients;
+    RefPtr<WebKitCSSResourceValue> m_cssMaskImageValue;
+    RefPtr<CachedResourceLoader> m_cachedResourceLoader;
+};
+
+} // namespace WebCore
+
+#endif // MaskImageOperation_h
index 7b5a528..912a5f5 100644 (file)
@@ -1017,31 +1017,31 @@ LayoutSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLaye
     return LayoutSize();
 }
 
-void RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatX(LayoutUnit xOffset)
+void BackgroundImageGeometry::setNoRepeatX(LayoutUnit xOffset)
 {
     m_destRect.move(std::max<LayoutUnit>(xOffset, 0), 0);
     m_phase.setX(-std::min<LayoutUnit>(xOffset, 0));
     m_destRect.setWidth(m_tileSize.width() + std::min<float>(xOffset, 0));
 }
-void RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatY(LayoutUnit yOffset)
+void BackgroundImageGeometry::setNoRepeatY(LayoutUnit yOffset)
 {
     m_destRect.move(0, std::max<LayoutUnit>(yOffset, 0));
     m_phase.setY(-std::min<LayoutUnit>(yOffset, 0));
     m_destRect.setHeight(m_tileSize.height() + std::min<float>(yOffset, 0));
 }
 
-void RenderBoxModelObject::BackgroundImageGeometry::useFixedAttachment(const LayoutPoint& attachmentPoint)
+void BackgroundImageGeometry::useFixedAttachment(const LayoutPoint& attachmentPoint)
 {
     FloatPoint alignedPoint = attachmentPoint;
     m_phase.move(std::max<LayoutUnit>(alignedPoint.x() - m_destRect.x(), 0), std::max<LayoutUnit>(alignedPoint.y() - m_destRect.y(), 0));
 }
 
-void RenderBoxModelObject::BackgroundImageGeometry::clip(const LayoutRect& clipRect)
+void BackgroundImageGeometry::clip(const LayoutRect& clipRect)
 {
     m_destRect.intersect(clipRect);
 }
 
-LayoutPoint RenderBoxModelObject::BackgroundImageGeometry::relativePhase() const
+LayoutPoint BackgroundImageGeometry::relativePhase() const
 {
     LayoutPoint phase = m_phase;
     phase += m_destRect.location() - m_destOrigin;
index 19558c6..0702d41 100644 (file)
@@ -65,6 +65,52 @@ class RenderNamedFlowFragment;
 class RenderTextFragment;
 class StickyPositionViewportConstraints;
 
+class BackgroundImageGeometry {
+public:
+    BackgroundImageGeometry()
+        : m_hasNonLocalGeometry(false)
+    { }
+
+    LayoutPoint destOrigin() const { return m_destOrigin; }
+    void setDestOrigin(const LayoutPoint& destOrigin) { m_destOrigin = destOrigin; }
+    
+    LayoutRect destRect() const { return m_destRect; }
+    void setDestRect(const LayoutRect& destRect) { m_destRect = destRect; }
+    
+    // Returns the phase relative to the destination rectangle.
+    LayoutPoint relativePhase() const;
+    
+    LayoutPoint phase() const { return m_phase; }
+    void setPhase(const LayoutPoint& phase) { m_phase = phase; }
+    
+    LayoutSize tileSize() const { return m_tileSize; }
+    void setTileSize(const LayoutSize& tileSize) { m_tileSize = tileSize; }
+    
+    LayoutSize spaceSize() const { return m_space; }
+    void setSpaceSize(const LayoutSize& space) { m_space = space; }
+    
+    void setPhaseX(LayoutUnit  x) { m_phase.setX(x); }
+    void setPhaseY(LayoutUnit y) { m_phase.setY(y); }
+    
+    void setNoRepeatX(LayoutUnit xOffset);
+    void setNoRepeatY(LayoutUnit yOffset);
+    
+    void useFixedAttachment(const LayoutPoint& attachmentPoint);
+    
+    void clip(const LayoutRect&);
+    
+    void setHasNonLocalGeometry(bool hasNonLocalGeometry = true) { m_hasNonLocalGeometry = hasNonLocalGeometry; }
+    bool hasNonLocalGeometry() const { return m_hasNonLocalGeometry; }
+    
+private:
+    LayoutRect m_destRect;
+    LayoutPoint m_destOrigin;
+    LayoutPoint m_phase;
+    LayoutSize m_tileSize;
+    LayoutSize m_space;
+    bool m_hasNonLocalGeometry; // Has background-attachment: fixed. Implies that we can't always cheaply compute destRect.
+};
+
 // This class is the base for all objects that adhere to the CSS box model as described
 // at http://www.w3.org/TR/CSS21/box.html
 
@@ -210,51 +256,6 @@ protected:
 
     virtual void willBeDestroyed() override;
 
-    class BackgroundImageGeometry {
-    public:
-        BackgroundImageGeometry()
-            : m_hasNonLocalGeometry(false)
-        { }
-        LayoutPoint destOrigin() const { return m_destOrigin; }
-        void setDestOrigin(const LayoutPoint& destOrigin) { m_destOrigin = destOrigin; }
-        
-        LayoutRect destRect() const { return m_destRect; }
-        void setDestRect(const LayoutRect& destRect) { m_destRect = destRect; }
-
-        // Returns the phase relative to the destination rectangle.
-        LayoutPoint relativePhase() const;
-        
-        LayoutPoint phase() const { return m_phase; }
-        void setPhase(const LayoutPoint& phase) { m_phase = phase; }
-
-        LayoutSize tileSize() const { return m_tileSize; }
-        void setTileSize(const LayoutSize& tileSize) { m_tileSize = tileSize; }
-
-        LayoutSize spaceSize() const { return m_space; }
-        void setSpaceSize(const LayoutSize& space) { m_space = space; }
-
-        void setPhaseX(LayoutUnit  x) { m_phase.setX(x); }
-        void setPhaseY(LayoutUnit y) { m_phase.setY(y); }
-        
-        void setNoRepeatX(LayoutUnit xOffset);
-        void setNoRepeatY(LayoutUnit yOffset);
-        
-        void useFixedAttachment(const LayoutPoint& attachmentPoint);
-        
-        void clip(const LayoutRect&);
-        
-        void setHasNonLocalGeometry(bool hasNonLocalGeometry = true) { m_hasNonLocalGeometry = hasNonLocalGeometry; }
-        bool hasNonLocalGeometry() const { return m_hasNonLocalGeometry; }
-
-    private:
-        LayoutRect m_destRect;
-        LayoutPoint m_destOrigin;
-        LayoutPoint m_phase;
-        LayoutSize m_tileSize;
-        LayoutSize m_space;
-        bool m_hasNonLocalGeometry; // Has background-attachment: fixed. Implies that we can't always cheaply compute destRect.
-    };
-
     LayoutPoint adjustedPositionRelativeToOffsetParent(const LayoutPoint&) const;
 
     bool hasBoxDecorationStyle() const;
index 92aa2af..d9d5d27 100644 (file)
@@ -88,6 +88,7 @@
 #include "RenderLayerBacking.h"
 #include "RenderLayerCompositor.h"
 #include "RenderLayerFilterInfo.h"
+#include "RenderLayerMaskImageInfo.h"
 #include "RenderMarquee.h"
 #include "RenderMultiColumnFlowThread.h"
 #include "RenderNamedFlowFragment.h"
@@ -189,6 +190,7 @@ RenderLayer::RenderLayer(RenderLayerModelObject& rendererLayerModelObject)
     , m_layerListMutationAllowed(true)
 #endif
     , m_hasFilterInfo(false)
+    , m_hasMaskImageInfo(false)
 #if ENABLE(CSS_COMPOSITING)
     , m_blendMode(BlendModeNormal)
     , m_hasNotIsolatedCompositedBlendingDescendants(false)
@@ -255,6 +257,7 @@ RenderLayer::~RenderLayer()
         removeReflection();
 
     FilterInfo::remove(*this);
+    MaskImageInfo::remove(*this);
 
     // Child layers will be deleted by their corresponding render objects, so
     // we don't need to delete them ourselves.
index 4109387..7313672 100644 (file)
@@ -1266,6 +1266,7 @@ private:
 #endif
 
     bool m_hasFilterInfo : 1;
+    unsigned m_hasMaskImageInfo : 1;
 
 #if ENABLE(CSS_COMPOSITING)
     unsigned m_blendMode : 5;
@@ -1342,6 +1343,7 @@ private:
     std::unique_ptr<RenderLayerBacking> m_backing;
 
     class FilterInfo;
+    class MaskImageInfo;
 };
 
 inline void RenderLayer::clearZOrderLists()
diff --git a/Source/WebCore/rendering/RenderLayerMaskImageInfo.cpp b/Source/WebCore/rendering/RenderLayerMaskImageInfo.cpp
new file mode 100644 (file)
index 0000000..a77fe08
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderLayerMaskImageInfo.h"
+
+#include "CachedSVGDocument.h"
+#include "CachedSVGDocumentReference.h"
+#include "RenderSVGResourceContainer.h"
+#include "SVGElement.h"
+#include "SVGMaskElement.h"
+#include <wtf/NeverDestroyed.h>
+
+namespace WebCore {
+
+HashMap<const RenderLayer*, std::unique_ptr<RenderLayer::MaskImageInfo>>& RenderLayer::MaskImageInfo::layerToMaskMap()
+{
+    static NeverDestroyed<HashMap<const RenderLayer*, std::unique_ptr<MaskImageInfo>>> layerToMaskMap;
+    return layerToMaskMap;
+}
+
+RenderLayer::MaskImageInfo* RenderLayer::MaskImageInfo::getIfExists(const RenderLayer& layer)
+{
+    ASSERT(layer.m_hasMaskImageInfo == layerToMaskMap().contains(&layer));
+    return layer.m_hasMaskImageInfo ? layerToMaskMap().get(&layer) : 0;
+}
+
+RenderLayer::MaskImageInfo& RenderLayer::MaskImageInfo::get(RenderLayer& layer)
+{
+    ASSERT(layer.m_hasMaskImageInfo == layerToMaskMap().contains(&layer));
+
+    auto& info = layerToMaskMap().add(&layer, nullptr).iterator->value;
+    if (!info) {
+        info = std::make_unique<MaskImageInfo>(layer);
+        layer.m_hasMaskImageInfo = true;
+    }
+    return *info;
+}
+
+void RenderLayer::MaskImageInfo::remove(RenderLayer& layer)
+{
+    ASSERT(layer.m_hasMaskImageInfo == layerToMaskMap().contains(&layer));
+
+    if (layerToMaskMap().remove(&layer))
+        layer.m_hasMaskImageInfo = false;
+}
+
+RenderLayer::MaskImageInfo::MaskImageInfo(RenderLayer& layer)
+    : m_layer(layer)
+{
+    m_svgDocumentClient = std::make_unique<MaskSVGDocumentClient>(this);
+    m_imageClient = std::make_unique<MaskImageClient>(this);
+}
+
+RenderLayer::MaskImageInfo::~MaskImageInfo()
+{
+    removeMaskImageClients();
+}
+
+void RenderLayer::MaskImageInfo::notifyFinished(CachedResource*)
+{
+    m_layer.renderer().repaint();
+}
+
+void RenderLayer::MaskImageInfo::imageChanged(CachedImage*, const IntRect*)
+{
+    m_layer.renderer().repaint();
+}
+
+void RenderLayer::MaskImageInfo::updateMaskImageClients()
+{
+    removeMaskImageClients();
+    
+    const FillLayer* maskLayer = m_layer.renderer().style().maskLayers();
+    while (maskLayer) {
+        const RefPtr<MaskImageOperation> maskImage = maskLayer->maskImage();
+        maskImage->setRenderLayerImageClient(m_imageClient.get());
+        CachedSVGDocumentReference* documentReference = maskImage->cachedSVGDocumentReference();
+        CachedSVGDocument* cachedSVGDocument = documentReference ? documentReference->document() : nullptr;
+        
+        if (cachedSVGDocument) {
+            // Reference is external; wait for notifyFinished().
+            cachedSVGDocument->addClient(m_svgDocumentClient.get());
+            m_externalSVGReferences.append(cachedSVGDocument);
+        } else {
+            // Reference is internal; add layer as a client so we can trigger
+            // mask repaint on SVG attribute change.
+            Element* masker = m_layer.renderer().document().getElementById(maskImage->fragment());
+            if (masker && is<SVGMaskElement>(masker)) {
+                downcast<SVGMaskElement>(masker)->addClientRenderLayer(&m_layer);
+                m_internalSVGReferences.append(masker);
+            }
+        }
+        
+        maskLayer = maskLayer->next();
+    }
+}
+
+void RenderLayer::MaskImageInfo::removeMaskImageClients()
+{
+    const FillLayer* maskLayer = m_layer.renderer().style().maskLayers();
+    while (maskLayer) {
+        if (maskLayer->maskImage())
+            maskLayer->maskImage()->setRenderLayerImageClient(nullptr);
+
+        maskLayer = maskLayer->next();
+    }
+    
+    for (auto externalSVGReference : m_externalSVGReferences)
+        externalSVGReference->removeClient(m_svgDocumentClient.get());
+    m_externalSVGReferences.clear();
+    
+    for (auto internalSVGReference : m_internalSVGReferences)
+        downcast<SVGMaskElement>(internalSVGReference.get())->removeClientRenderLayer(&m_layer);
+    m_internalSVGReferences.clear();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderLayerMaskImageInfo.h b/Source/WebCore/rendering/RenderLayerMaskImageInfo.h
new file mode 100644 (file)
index 0000000..1d5079f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef RenderLayerMaskImageInfo_h
+#define RenderLayerMaskImageInfo_h
+
+#include "CachedImageClient.h"
+#include "CachedResourceHandle.h"
+#include "CachedSVGDocumentClient.h"
+#include "MaskImageOperation.h"
+#include "RenderLayer.h"
+#include <memory>
+
+namespace WebCore {
+
+class Element;
+
+class RenderLayer::MaskImageInfo final {
+private:
+    class MaskResourceClient {
+    public:
+        MaskResourceClient(RenderLayer::MaskImageInfo* maskImageInfo)
+            : m_maskImageInfo(maskImageInfo)
+        {
+            ASSERT(m_maskImageInfo);
+        }
+    protected:
+        RenderLayer::MaskImageInfo* m_maskImageInfo;
+    };
+    
+    class MaskSVGDocumentClient : public MaskResourceClient, public CachedSVGDocumentClient {
+    public:
+        MaskSVGDocumentClient(RenderLayer::MaskImageInfo* maskImageInfo)
+            : MaskResourceClient(maskImageInfo)
+        {
+        }
+        
+        virtual void notifyFinished(CachedResource* resource) override { m_maskImageInfo->notifyFinished(resource); }
+    };
+    
+    class MaskImageClient : public MaskResourceClient, public CachedImageClient {
+    public:
+        MaskImageClient(RenderLayer::MaskImageInfo* maskImageInfo)
+            : MaskResourceClient(maskImageInfo)
+        {
+        }
+        
+        virtual void imageChanged(CachedImage* image, const IntRect* rect = nullptr) override { m_maskImageInfo->imageChanged(image, rect); }
+    };
+
+public:
+    static MaskImageInfo& get(RenderLayer&);
+    static MaskImageInfo* getIfExists(const RenderLayer&);
+    static void remove(RenderLayer&);
+
+    explicit MaskImageInfo(RenderLayer&);
+    ~MaskImageInfo();
+
+    void updateMaskImageClients();
+    void removeMaskImageClients();
+
+private:
+    friend void WTF::deleteOwnedPtr<MaskImageInfo>(MaskImageInfo*);
+
+    void notifyFinished(CachedResource*);
+    void imageChanged(CachedImage*, const IntRect*);
+
+    static HashMap<const RenderLayer*, std::unique_ptr<MaskImageInfo>>& layerToMaskMap();
+
+    RenderLayer& m_layer;
+
+    Vector<RefPtr<Element>> m_internalSVGReferences;
+    Vector<CachedResourceHandle<CachedSVGDocument>> m_externalSVGReferences;
+    std::unique_ptr<MaskSVGDocumentClient> m_svgDocumentClient;
+    std::unique_ptr<MaskImageClient> m_imageClient;
+};
+
+} // namespace WebCore
+
+#endif // RenderLayerMaskImageInfo_h
index b91fbe7..82d9365 100644 (file)
@@ -28,6 +28,7 @@ struct SameSizeAsFillLayer {
     FillLayer* next;
 
     RefPtr<StyleImage> image;
+    RefPtr<MaskImageOperation> maskImageOperation;
 
     Length x;
     Length y;
@@ -74,6 +75,7 @@ FillLayer::FillLayer(EFillLayerType type)
 
 FillLayer::FillLayer(const FillLayer& o)
     : m_next(o.m_next ? std::make_unique<FillLayer>(*o.m_next) : nullptr)
+    , m_maskImageOperation(o.m_maskImageOperation)
     , m_image(o.m_image)
     , m_xPosition(o.m_xPosition)
     , m_yPosition(o.m_yPosition)
@@ -116,6 +118,7 @@ FillLayer& FillLayer::operator=(const FillLayer& o)
     m_next = o.m_next ? std::make_unique<FillLayer>(*o.m_next) : nullptr;
 
     m_image = o.m_image;
+    m_maskImageOperation = o.m_maskImageOperation;
     m_xPosition = o.m_xPosition;
     m_yPosition = o.m_yPosition;
     m_backgroundXOrigin = o.m_backgroundXOrigin;
@@ -153,7 +156,8 @@ bool FillLayer::operator==(const FillLayer& o) const
 {
     // We do not check the "isSet" booleans for each property, since those are only used during initial construction
     // to propagate patterns into layers. All layer comparisons happen after values have all been filled in anyway.
-    return StyleImage::imagesEquivalent(m_image.get(), o.m_image.get()) && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition
+    return StyleImage::imagesEquivalent(m_image.get(), o.m_image.get()) && m_maskImageOperation == o.m_maskImageOperation
+        && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition
         && m_backgroundXOrigin == o.m_backgroundXOrigin && m_backgroundYOrigin == o.m_backgroundYOrigin
         && m_attachment == o.m_attachment && m_clip == o.m_clip && m_composite == o.m_composite
         && m_blendMode == o.m_blendMode && m_origin == o.m_origin && m_repeatX == o.m_repeatX
@@ -288,13 +292,21 @@ void FillLayer::fillUnsetProperties()
 void FillLayer::cullEmptyLayers()
 {
     for (FillLayer* layer = this; layer; layer = layer->m_next.get()) {
-        if (layer->m_next && !layer->m_next->isImageSet()) {
+        if (layer->m_next && !layer->m_next->isImageSet() && !layer->m_next->hasMaskImage()) {
             layer->m_next = nullptr;
             break;
         }
     }
 }
 
+bool FillLayer::hasNonEmptyMaskImage() const
+{
+    if (hasMaskImage() && !maskImage()->isCSSValueNone())
+        return true;
+    
+    return (next() ? next()->hasNonEmptyMaskImage() : false);
+}
+
 static inline EFillBox clipMax(EFillBox clipA, EFillBox clipB)
 {
     if (clipA == BorderFillBox || clipB == BorderFillBox)
@@ -340,6 +352,9 @@ bool FillLayer::imagesAreLoaded() const
     for (auto* layer = this; layer; layer = layer->m_next.get()) {
         if (layer->m_image && !layer->m_image->isLoaded())
             return false;
+        
+        if (layer->hasMaskImage() && !layer->maskImage()->isMaskLoaded())
+            return false;
     }
     return true;
 }
index 9beb7bf..df4487a 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "GraphicsTypes.h"
 #include "LengthSize.h"
+#include "MaskImageOperation.h"
 #include "RenderStyleConstants.h"
 #include "StyleImage.h"
 #include <wtf/RefPtr.h>
@@ -67,7 +68,9 @@ public:
     explicit FillLayer(EFillLayerType);
     ~FillLayer();
 
+    const RefPtr<MaskImageOperation>& maskImage() const { return m_maskImageOperation; }
     StyleImage* image() const { return m_image.get(); }
+    StyleImage* imageOrMaskImage() const { return hasMaskImage() ? maskImage()->image() : image(); }
     const Length& xPosition() const { return m_xPosition; }
     const Length& yPosition() const { return m_yPosition; }
     BackgroundEdgeOrigin backgroundXOrigin() const { return static_cast<BackgroundEdgeOrigin>(m_backgroundXOrigin); }
@@ -101,6 +104,7 @@ public:
     bool isSizeSet() const { return m_sizeType != SizeNone; }
     bool isMaskSourceTypeSet() const { return m_maskSourceTypeSet; }
 
+    void setMaskImage(PassRefPtr<MaskImageOperation> maskImage) { m_maskImageOperation = maskImage; }
     void setImage(PassRefPtr<StyleImage> image) { m_image = image; m_imageSet = true; }
     void setXPosition(Length length) { m_xPosition = WTF::move(length); m_xPosSet = true; }
     void setYPosition(Length length) { m_yPosition = WTF::move(length); m_yPosSet = true; }
@@ -118,6 +122,7 @@ public:
     void setSize(FillSize f) { m_sizeType = f.type; m_sizeLength = f.size; }
     void setMaskSourceType(EMaskSourceType m) { m_maskSourceType = m; m_maskSourceTypeSet = true; }
 
+    void clearMaskImage() { m_maskImageOperation.clear(); }
     void clearImage() { m_image.clear(); m_imageSet = false; }
     void clearXPosition() { m_xPosSet = false; m_backgroundOriginSet = false; }
     void clearYPosition() { m_yPosSet = false; m_backgroundOriginSet = false; }
@@ -143,6 +148,8 @@ public:
     bool containsImage(StyleImage&) const;
     bool imagesAreLoaded() const;
     bool hasImage() const;
+    bool hasMaskImage() const { return maskImage().get(); }
+    bool hasNonEmptyMaskImage() const;
     bool hasFixedImage() const;
     bool hasOpaqueImage(const RenderElement&) const;
     bool hasRepeatXY() const;
@@ -175,6 +182,7 @@ private:
 
     std::unique_ptr<FillLayer> m_next;
 
+    RefPtr<MaskImageOperation> m_maskImageOperation;
     RefPtr<StyleImage> m_image;
 
     Length m_xPosition;
index 37f2c09..10bc0ab 100644 (file)
@@ -25,6 +25,7 @@
 #include "FloatPoint.h"
 #include "Image.h"
 #include "IntRect.h"
+#include "RenderBoxModelObject.h"
 #include "SVGRenderingContext.h"
 
 namespace WebCore {
@@ -53,10 +54,9 @@ void RenderSVGResourceMasker::removeClientFromCache(RenderElement& client, bool
     markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation);
 }
 
-bool RenderSVGResourceMasker::applyResource(RenderElement& renderer, const RenderStyle&, GraphicsContext*& context, unsigned short resourceMode)
+bool RenderSVGResourceMasker::applySVGMask(RenderElement& renderer, GraphicsContext*& context, bool applyClip)
 {
     ASSERT(context);
-    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
 
     bool missingMaskerData = !m_masker.contains(&renderer);
     if (missingMaskerData)
@@ -75,18 +75,25 @@ bool RenderSVGResourceMasker::applyResource(RenderElement& renderer, const Rende
         if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskerData->maskImage, colorSpace, Unaccelerated))
             return false;
 
-        if (!drawContentIntoMaskImage(maskerData, colorSpace, &renderer)) {
+        if (!drawContentIntoMaskImage(maskerData, colorSpace, &renderer))
             maskerData->maskImage.reset();
-        }
     }
 
     if (!maskerData->maskImage)
         return false;
 
-    SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, maskerData->maskImage, missingMaskerData);
+    if (applyClip)
+        SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, maskerData->maskImage, missingMaskerData);
+
     return true;
 }
 
+bool RenderSVGResourceMasker::applyResource(RenderElement& renderer, const RenderStyle&, GraphicsContext*& context, unsigned short resourceMode)
+{
+    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
+    return applySVGMask(renderer, context, true);
+}
+
 bool RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, ColorSpace colorSpace, RenderObject* object)
 {
     GraphicsContext* maskImageContext = maskerData->maskImage->context();
@@ -127,6 +134,34 @@ bool RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, C
     return true;
 }
 
+void RenderSVGResourceMasker::drawMaskForRenderer(RenderElement& renderer, const BackgroundImageGeometry& geometry, GraphicsContext* context, CompositeOperator compositeOp)
+{
+    if (context->paintingDisabled())
+        return;
+
+    if (!applySVGMask(renderer, context, false))
+        return;
+
+    MaskerData* maskerData = maskerDataForRenderer(renderer);
+    ASSERT(maskerData);
+
+    FloatRect oneTileRect;
+    FloatSize actualTileSize(geometry.tileSize().width() + geometry.spaceSize().width(), geometry.tileSize().height() + geometry.spaceSize().height());
+    oneTileRect.setX(geometry.destRect().x() + fmodf(fmodf(-geometry.relativePhase().x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width()));
+    oneTileRect.setY(geometry.destRect().y() + fmodf(fmodf(-geometry.relativePhase().y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height()));
+    oneTileRect.setSize(geometry.tileSize());
+    
+    FloatSize intrinsicTileSize = maskerData->maskImage->logicalSize();
+    FloatSize scale(geometry.tileSize().width() / intrinsicTileSize.width(), geometry.tileSize().height() / intrinsicTileSize.height());
+    
+    FloatRect visibleSrcRect;
+    visibleSrcRect.setX((geometry.destRect().x() - oneTileRect.x()) / scale.width());
+    visibleSrcRect.setY((geometry.destRect().y() - oneTileRect.y()) / scale.height());
+    visibleSrcRect.setWidth(geometry.destRect().width() / scale.width());
+    visibleSrcRect.setHeight(geometry.destRect().height() / scale.height());
+    context->drawImageBuffer(maskerData->maskImage.get(), ColorSpaceDeviceRGB, geometry.destRect(), visibleSrcRect, compositeOp);
+}
+
 void RenderSVGResourceMasker::calculateMaskContentRepaintRect()
 {
     for (Node* childNode = maskElement().firstChild(); childNode; childNode = childNode->nextSibling()) {
index a1ffb3f..7cd74dc 100644 (file)
@@ -45,6 +45,7 @@ public:
     virtual void removeAllClientsFromCache(bool markForInvalidation = true) override;
     virtual void removeClientFromCache(RenderElement&, bool markForInvalidation = true) override;
     virtual bool applyResource(RenderElement&, const RenderStyle&, GraphicsContext*&, unsigned short resourceMode) override;
+    bool applySVGMask(RenderElement& renderer, GraphicsContext*&, bool applyClip);
     virtual FloatRect resourceBoundingBox(const RenderObject&) override;
 
     SVGUnitTypes::SVGUnitType maskUnits() const { return maskElement().maskUnits(); }
@@ -52,6 +53,9 @@ public:
 
     virtual RenderSVGResourceType resourceType() const override { return MaskerResourceType; }
 
+    MaskerData* maskerDataForRenderer(RenderObject& renderer) { return m_masker.get(&renderer); }
+    void drawMaskForRenderer(RenderElement& renderer, const BackgroundImageGeometry&, GraphicsContext*, CompositeOperator);
+
 private:
     void element() const = delete;
 
index 431f26a..6f6291e 100644 (file)
@@ -161,7 +161,33 @@ void SVGMaskElement::childrenChanged(const ChildChange& change)
 
 RenderPtr<RenderElement> SVGMaskElement::createElementRenderer(PassRef<RenderStyle> style)
 {
-    return createRenderer<RenderSVGResourceMasker>(*this, WTF::move(style));
+    RenderPtr<RenderElement> maskRenderer = createRenderer<RenderSVGResourceMasker>(*this, WTF::move(style));
+    
+    // Pass along existing render layer clients.
+    for (auto* clientLayer : m_clientLayers)
+        static_cast<RenderSVGResourceMasker*>(maskRenderer.get())->addClientRenderLayer(clientLayer);
+    
+    return maskRenderer;
+}
+
+void SVGMaskElement::addClientRenderLayer(RenderLayer* client)
+{
+    ASSERT(client);
+    m_clientLayers.add(client);
+    
+    // Pass it along to the renderer.
+    if (renderer())
+        static_cast<RenderSVGResourceMasker*>(renderer())->addClientRenderLayer(client);
+}
+
+void SVGMaskElement::removeClientRenderLayer(RenderLayer* client)
+{
+    ASSERT(client);
+    m_clientLayers.remove(client);
+    
+    // Pass it along to the renderer.
+    if (renderer())
+        static_cast<RenderSVGResourceMasker*>(renderer())->removeClientRenderLayer(client);
 }
 
 }
index 22eddbc..d46c702 100644 (file)
@@ -30,6 +30,8 @@
 #include "SVGUnitTypes.h"
 
 namespace WebCore {
+    
+class RenderLayer;
 
 class SVGMaskElement final : public SVGElement,
                              public SVGTests,
@@ -37,6 +39,9 @@ class SVGMaskElement final : public SVGElement,
 public:
     static PassRefPtr<SVGMaskElement> create(const QualifiedName&, Document&);
 
+    void addClientRenderLayer(RenderLayer*);
+    void removeClientRenderLayer(RenderLayer*);
+
 private:
     SVGMaskElement(const QualifiedName&, Document&);
 
@@ -48,6 +53,8 @@ private:
     virtual void svgAttributeChanged(const QualifiedName&) override;
     virtual void childrenChanged(const ChildChange&) override;
 
+    HashSet<RenderLayer*> m_clientLayers;
+
     virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override;
 
     virtual bool selfHasRelativeLengths() const override { return true; }
index 52951bc..42bc8f1 100644 (file)
@@ -992,8 +992,11 @@ void SVGUseElement::setCachedDocument(CachedResourceHandle<CachedSVGDocument> ca
         m_cachedDocument->removeClient(this);
 
     m_cachedDocument = cachedDocument;
-    if (m_cachedDocument)
+    if (m_cachedDocument) {
+        // We don't need the SVG document to create a new frame because the new document belongs to the parent UseElement.
+        m_cachedDocument->setShouldCreateFrameForDocument(false);
         m_cachedDocument->addClient(this);
+    }
 }
 
 }
index 49b90be..57215d9 100644 (file)
@@ -344,6 +344,8 @@ bool SVGImage::dataChanged(bool allDataReceived)
         fillWithEmptyClients(pageConfiguration);
         m_chromeClient = std::make_unique<SVGImageChromeClient>(this);
         pageConfiguration.chromeClient = m_chromeClient.get();
+        bool canHaveScrollbars = false; // SVG Images will always synthesize a viewBox, if it's not available, and thus never see scrollbars.
+        bool transparent = true; // SVG Images are transparent.
 
         // FIXME: If this SVG ends up loading itself, we might leak the world.
         // The Cache code does not know about CachedImages holding Frames and
@@ -351,25 +353,7 @@ bool SVGImage::dataChanged(bool allDataReceived)
         // This will become an issue when SVGImage will be able to load other
         // SVGImage objects, but we're safe now, because SVGImage can only be
         // loaded by a top-level document.
-        m_page = std::make_unique<Page>(pageConfiguration);
-        m_page->settings().setMediaEnabled(false);
-        m_page->settings().setScriptEnabled(false);
-        m_page->settings().setPluginsEnabled(false);
-
-        Frame& frame = m_page->mainFrame();
-        frame.setView(FrameView::create(frame));
-        frame.init();
-        FrameLoader& loader = frame.loader();
-        loader.forceSandboxFlags(SandboxAll);
-
-        frame.view()->setCanHaveScrollbars(false); // SVG Images will always synthesize a viewBox, if it's not available, and thus never see scrollbars.
-        frame.view()->setTransparent(true); // SVG Images are transparent.
-
-        ASSERT(loader.activeDocumentLoader()); // DocumentLoader should have been created by frame->init().
-        loader.activeDocumentLoader()->writer().setMIMEType("image/svg+xml");
-        loader.activeDocumentLoader()->writer().begin(URL()); // create the empty document
-        loader.activeDocumentLoader()->writer().addData(data()->data(), data()->size());
-        loader.activeDocumentLoader()->writer().end();
+        m_page = Page::createPageFromBuffer(pageConfiguration, data(), "image/svg+xml", canHaveScrollbars, transparent);
 
         // Set the intrinsic size before a container size is available.
         m_intrinsicSize = containerSize();