Bug 652991 - Part 2. Re-evaluate url before painting; draft
authorCJKu <cku@mozilla.com>
Tue, 03 May 2016 18:14:22 +0800
changeset 362845 fe3dfab6dfd4a97531d1d5e9c7c81213ccc5c00e
parent 362844 546b7103f08dce90652681c0800960deda3c46e8
child 362846 2dd2ff9e94f7c55ba65dca7bd3759a86b3b2636a
push id17044
push usercku@mozilla.com
push dateTue, 03 May 2016 10:15:34 +0000
bugs652991
milestone49.0a1
Bug 652991 - Part 2. Re-evaluate url before painting; MozReview-Commit-ID: KgsKKfNNWp1
layout/svg/nsSVGEffects.cpp
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -48,16 +48,41 @@ nsSVGRenderingObserver::StopListening()
 
 static nsSVGRenderingObserverList *
 GetObserverList(Element *aElement)
 {
   return static_cast<nsSVGRenderingObserverList*>
     (aElement->GetProperty(nsGkAtoms::renderingobserverlist));
 }
 
+static already_AddRefed<nsIURI>
+ResolveLocalReferencedURL(nsIURI* aURI, nsIContent* aElement)
+{
+  nsCOMPtr<nsIURI> result;
+
+  if (!aURI) {
+    return result.forget();
+  }
+
+  bool isLocalRef = false;
+  aURI->GetIsLocalRef(&isLocalRef);
+  if (isLocalRef) {
+    nsCOMPtr<nsIURI> baseURI= aElement->GetBaseURI();
+    baseURI->Clone(getter_AddRefs(result));
+
+    nsAutoCString ref;
+    aURI->GetRef(ref);
+    result->SetRef(ref);
+  } else {
+    result = aURI;
+  }
+
+  return result.forget();
+}
+
 Element*
 nsSVGRenderingObserver::GetReferencedElement()
 {
   Element* target = GetTarget();
 #ifdef DEBUG
   if (target) {
     nsSVGRenderingObserverList *observerList = GetObserverList(target);
     bool inObserverList = observerList && observerList->Contains(this);
@@ -550,28 +575,35 @@ nsSVGEffects::EffectProperties
 nsSVGEffects::GetEffectProperties(nsIFrame *aFrame)
 {
   NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
 
   EffectProperties result;
   const nsStyleSVGReset *style = aFrame->StyleSVGReset();
   result.mFilter = GetOrCreateFilterProperty(aFrame);
   if (style->mClipPath.GetType() == NS_STYLE_CLIP_PATH_URL) {
+    nsCOMPtr<nsIURI> effectURL =
+      ResolveLocalReferencedURL(style->mClipPath.GetURL(), aFrame->GetContent());
+
     result.mClipPath =
-      GetPaintingProperty(style->mClipPath.GetURL(), aFrame, ClipPathProperty());
+      GetPaintingProperty(effectURL, aFrame, ClipPathProperty());
   } else {
     result.mClipPath = nullptr;
   }
 
   // FIXME: Bug 1228280.
   // Before fixing bug 1228280, we support only single svg mask as before.
   MOZ_ASSERT(style->mMask.mImageCount > 0);
-  nsCOMPtr<nsIURI> uri = style->mMask.mLayers[0].mSourceURI;
-  result.mMask = uri ? GetPaintingProperty(uri, aFrame, MaskProperty()) :
-                         nullptr;
+  nsCOMPtr<nsIURI> effectURL =
+    ResolveLocalReferencedURL(style->mMask.mLayers[0].mSourceURI,
+                              aFrame->GetContent());
+
+  result.mMask = effectURL
+                 ? GetPaintingProperty(effectURL, aFrame, MaskProperty())
+                 : nullptr;
 
   return result;
 }
 
 nsSVGPaintServerFrame *
 nsSVGEffects::GetPaintServer(nsIFrame *aTargetFrame, const nsStyleSVGPaint *aPaint,
                              ObserverPropertyDescriptor aType)
 {
@@ -585,18 +617,23 @@ nsSVGEffects::GetPaintServer(nsIFrame *a
   nsIFrame* frame = aTargetFrame;
   if (frame->GetContent()->IsNodeOfType(nsINode::eTEXT)) {
     frame = frame->GetParent();
     nsIFrame* grandparent = frame->GetParent();
     if (grandparent && grandparent->GetType() == nsGkAtoms::svgTextFrame) {
       frame = grandparent;
     }
   }
+
+  nsCOMPtr<nsIURI> effectURL =
+    ResolveLocalReferencedURL(aPaint->mPaint.mPaintServer,
+                              aTargetFrame->GetContent());
+
   nsSVGPaintingProperty *property =
-    nsSVGEffects::GetPaintingProperty(aPaint->mPaint.mPaintServer, frame, aType);
+    nsSVGEffects::GetPaintingProperty(effectURL, frame, aType);
   if (!property)
     return nullptr;
   nsIFrame *result = property->GetReferencedFrame();
   if (!result)
     return nullptr;
 
   nsIAtom *type = result->GetType();
   if (type != nsGkAtoms::svgLinearGradientFrame &&
@@ -649,21 +686,25 @@ nsSVGEffects::UpdateEffects(nsIFrame *aF
   // Ensure that the filter is repainted correctly
   // We can't do that in DoUpdate as the referenced frame may not be valid
   GetOrCreateFilterProperty(aFrame);
 
   if (aFrame->GetType() == nsGkAtoms::svgPathGeometryFrame &&
       static_cast<nsSVGPathGeometryElement*>(aFrame->GetContent())->IsMarkable()) {
     // Set marker properties here to avoid reference loops
     const nsStyleSVG *style = aFrame->StyleSVG();
-    GetEffectProperty(style->mMarkerStart, aFrame, MarkerBeginProperty(),
+    nsCOMPtr<nsIURI> effectURL;
+    effectURL = ResolveLocalReferencedURL(style->mMarkerStart, aFrame->GetContent());
+    GetEffectProperty(effectURL, aFrame, MarkerBeginProperty(),
                       CreateMarkerProperty);
-    GetEffectProperty(style->mMarkerMid, aFrame, MarkerMiddleProperty(),
+    effectURL = ResolveLocalReferencedURL(style->mMarkerMid, aFrame->GetContent());
+    GetEffectProperty(effectURL, aFrame, MarkerMiddleProperty(),
                       CreateMarkerProperty);
-    GetEffectProperty(style->mMarkerEnd, aFrame, MarkerEndProperty(),
+    effectURL = ResolveLocalReferencedURL(style->mMarkerEnd, aFrame->GetContent());
+    GetEffectProperty(effectURL, aFrame, MarkerEndProperty(),
                       CreateMarkerProperty);
   }
 }
 
 nsSVGFilterProperty *
 nsSVGEffects::GetFilterProperty(nsIFrame *aFrame)
 {
   NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");