Bug 652991 - Part 3. Using FragmentOrURL to represent SVG maker url.
MozReview-Commit-ID: IQDGL7j5p1q
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -5598,51 +5598,51 @@ nsComputedDOMStyle::DoGetStroke()
{
return GetSVGPaintFor(false);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMarkerEnd()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-
- const nsStyleSVG* svg = StyleSVG();
-
- if (svg->mMarkerEnd)
- val->SetURI(svg->mMarkerEnd);
+ // Bug 1288812 - we should only serialize fragment for local-ref URL.
+ nsCOMPtr<nsIURI> markerURI = StyleSVG()->mMarkerEnd.GetSourceURL();
+
+ if (markerURI)
+ val->SetURI(markerURI);
else
val->SetIdent(eCSSKeyword_none);
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMarkerMid()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-
- const nsStyleSVG* svg = StyleSVG();
-
- if (svg->mMarkerMid)
- val->SetURI(svg->mMarkerMid);
+ // Bug 1288812 - we should only serialize fragment for local-ref URL.
+ nsCOMPtr<nsIURI> markerURI = StyleSVG()->mMarkerMid.GetSourceURL();
+
+ if (markerURI)
+ val->SetURI(markerURI);
else
val->SetIdent(eCSSKeyword_none);
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMarkerStart()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-
- const nsStyleSVG* svg = StyleSVG();
-
- if (svg->mMarkerStart)
- val->SetURI(svg->mMarkerStart);
+ // Bug 1288812 - we should only serialize fragment for local-ref URL.
+ nsCOMPtr<nsIURI> markerURI = StyleSVG()->mMarkerStart.GetSourceURL();
+
+ if (markerURI)
+ val->SetURI(markerURI);
else
val->SetIdent(eCSSKeyword_none);
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetStrokeDasharray()
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -9362,46 +9362,46 @@ nsRuleNode::ComputeSVGData(void* aStartS
svg->mFillRule, conditions,
SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
parentSVG->mFillRule,
NS_STYLE_FILL_RULE_NONZERO);
// marker-end: url, none, inherit
const nsCSSValue* markerEndValue = aRuleData->ValueForMarkerEnd();
if (eCSSUnit_URL == markerEndValue->GetUnit()) {
- svg->mMarkerEnd = markerEndValue->GetURLValue();
+ svg->mMarkerEnd.SetValue(markerEndValue);
} else if (eCSSUnit_None == markerEndValue->GetUnit() ||
eCSSUnit_Initial == markerEndValue->GetUnit()) {
- svg->mMarkerEnd = nullptr;
+ svg->mMarkerEnd.SetNull();
} else if (eCSSUnit_Inherit == markerEndValue->GetUnit() ||
eCSSUnit_Unset == markerEndValue->GetUnit()) {
conditions.SetUncacheable();
svg->mMarkerEnd = parentSVG->mMarkerEnd;
}
// marker-mid: url, none, inherit
const nsCSSValue* markerMidValue = aRuleData->ValueForMarkerMid();
if (eCSSUnit_URL == markerMidValue->GetUnit()) {
- svg->mMarkerMid = markerMidValue->GetURLValue();
+ svg->mMarkerMid.SetValue(markerMidValue);
} else if (eCSSUnit_None == markerMidValue->GetUnit() ||
eCSSUnit_Initial == markerMidValue->GetUnit()) {
- svg->mMarkerMid = nullptr;
+ svg->mMarkerMid.SetNull();
} else if (eCSSUnit_Inherit == markerMidValue->GetUnit() ||
eCSSUnit_Unset == markerMidValue->GetUnit()) {
conditions.SetUncacheable();
svg->mMarkerMid = parentSVG->mMarkerMid;
}
// marker-start: url, none, inherit
const nsCSSValue* markerStartValue = aRuleData->ValueForMarkerStart();
if (eCSSUnit_URL == markerStartValue->GetUnit()) {
- svg->mMarkerStart = markerStartValue->GetURLValue();
+ svg->mMarkerStart.SetValue(markerStartValue);
} else if (eCSSUnit_None == markerStartValue->GetUnit() ||
eCSSUnit_Initial == markerStartValue->GetUnit()) {
- svg->mMarkerStart = nullptr;
+ svg->mMarkerStart.SetNull();
} else if (eCSSUnit_Inherit == markerStartValue->GetUnit() ||
eCSSUnit_Unset == markerStartValue->GetUnit()) {
conditions.SetUncacheable();
svg->mMarkerStart = parentSVG->mMarkerStart;
}
// paint-order: enum (bit field), inherit, initial
const nsCSSValue* paintOrderValue = aRuleData->ValueForPaintOrder();
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -916,19 +916,18 @@ PaintURIChanged(const nsStyleSVGPaint& a
!EqualURIs(aPaint1.mPaint.mPaintServer, aPaint2.mPaint.mPaintServer);
}
nsChangeHint
nsStyleSVG::CalcDifference(const nsStyleSVG& aNewData) const
{
nsChangeHint hint = nsChangeHint(0);
- if (!EqualURIs(mMarkerEnd, aNewData.mMarkerEnd) ||
- !EqualURIs(mMarkerMid, aNewData.mMarkerMid) ||
- !EqualURIs(mMarkerStart, aNewData.mMarkerStart)) {
+ if (mMarkerEnd != aNewData.mMarkerEnd || mMarkerMid != aNewData.mMarkerMid ||
+ mMarkerStart != aNewData.mMarkerStart) {
// Markers currently contribute to nsSVGPathGeometryFrame::mRect,
// so we need a reflow as well as a repaint. No intrinsic sizes need
// to change, so nsChangeHint_NeedReflow is sufficient.
return nsChangeHint_UpdateEffects |
nsChangeHint_NeedReflow |
nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
nsChangeHint_RepaintFrame;
}
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -3306,19 +3306,19 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
// CalcDifference never returns nsChangeHint_NeedReflow as a hint
// not handled for descendants, and never returns
// nsChangeHint_ClearAncestorIntrinsics at all.
return nsChangeHint_NeedReflow;
}
nsStyleSVGPaint mFill; // [inherited]
nsStyleSVGPaint mStroke; // [inherited]
- nsCOMPtr<nsIURI> mMarkerEnd; // [inherited]
- nsCOMPtr<nsIURI> mMarkerMid; // [inherited]
- nsCOMPtr<nsIURI> mMarkerStart; // [inherited]
+ FragmentOrURL mMarkerEnd; // [inherited]
+ FragmentOrURL mMarkerMid; // [inherited]
+ FragmentOrURL mMarkerStart; // [inherited]
nsTArray<nsStyleCoord> mStrokeDasharray; // [inherited] coord, percent, factor
nsStyleCoord mStrokeDashoffset; // [inherited] coord, percent, factor
nsStyleCoord mStrokeWidth; // [inherited] coord, percent, factor
float mFillOpacity; // [inherited]
float mStrokeMiterlimit; // [inherited]
float mStrokeOpacity; // [inherited]
@@ -3370,17 +3370,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
(aValue ? STROKE_DASHOFFSET_CONTEXT : 0);
}
void SetStrokeWidthFromObject(bool aValue) {
mContextFlags = (mContextFlags & ~STROKE_WIDTH_CONTEXT) |
(aValue ? STROKE_WIDTH_CONTEXT : 0);
}
bool HasMarker() const {
- return mMarkerStart || mMarkerMid || mMarkerEnd;
+ return mMarkerStart.GetSourceURL() || mMarkerMid.GetSourceURL() ||
+ mMarkerEnd.GetSourceURL();
}
/**
* Returns true if the stroke is not "none" and the stroke-opacity is greater
* than zero. This ignores stroke-widths as that depends on the context.
*/
bool HasStroke() const {
return mStroke.mType != eStyleSVGPaintType_None && mStrokeOpacity > 0;
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -13,16 +13,17 @@
#include "nsISupportsImpl.h"
#include "nsSVGClipPathFrame.h"
#include "nsSVGPaintServerFrame.h"
#include "nsSVGPathGeometryElement.h"
#include "nsSVGFilterFrame.h"
#include "nsSVGMaskFrame.h"
#include "nsIReflowCallback.h"
#include "nsCycleCollectionParticipant.h"
+#include "SVGUseElement.h"
using namespace mozilla;
using namespace mozilla::dom;
void
nsSVGRenderingObserver::StartListening()
{
Element* target = GetTarget();
@@ -689,20 +690,23 @@ 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();
- GetMarkerProperty(style->mMarkerStart, aFrame, MarkerBeginProperty());
- GetMarkerProperty(style->mMarkerMid, aFrame, MarkerMiddleProperty());
- GetMarkerProperty(style->mMarkerEnd, aFrame, MarkerEndProperty());
+ nsCOMPtr<nsIURI> markerURL =
+ nsSVGEffects::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerStart);
+ GetMarkerProperty(markerURL, aFrame, MarkerBeginProperty());
+ markerURL = nsSVGEffects::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerMid);
+ GetMarkerProperty(markerURL, aFrame, MarkerMiddleProperty());
+ markerURL = nsSVGEffects::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerEnd);
+ GetMarkerProperty(markerURL, aFrame, MarkerEndProperty());
}
}
nsSVGFilterProperty *
nsSVGEffects::GetFilterProperty(nsIFrame *aFrame)
{
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
@@ -864,8 +868,45 @@ nsSVGEffects::InvalidateDirectRenderingO
void
nsSVGEffects::InvalidateDirectRenderingObservers(nsIFrame *aFrame, uint32_t aFlags /* = 0 */)
{
nsIContent* content = aFrame->GetContent();
if (content && content->IsElement()) {
InvalidateDirectRenderingObservers(content->AsElement(), aFlags);
}
}
+
+static already_AddRefed<nsIURI>
+ResolveFragmentOrURL(nsIFrame* aFrame, const FragmentOrURL* aFragmentOrURL)
+{
+ MOZ_ASSERT(aFrame);
+
+ if (!aFragmentOrURL) {
+ return nullptr;
+ }
+
+ // Non-local-reference URL.
+ if (!aFragmentOrURL->IsLocalRef()) {
+ nsCOMPtr<nsIURI> result = aFragmentOrURL->GetSourceURL();
+ return result.forget();
+ }
+
+ nsIContent* content = aFrame->GetContent();
+ nsCOMPtr<nsIURI> baseURI = content->GetBaseURI();
+
+ if (content->IsInAnonymousSubtree()) {
+ // content is in a shadow tree.
+ // Depending on where this url comes from, choose either the baseURI of the
+ // original document of content or the root document of the shadow tree
+ // to resolve URI.
+ if (!aFragmentOrURL->EqualsExceptRef(baseURI))
+ baseURI = content->OwnerDoc()->GetBaseURI();
+ }
+
+ return aFragmentOrURL->Resolve(baseURI);
+}
+
+already_AddRefed<nsIURI>
+nsSVGEffects::GetMarkerURI(nsIFrame* aFrame,
+ FragmentOrURL nsStyleSVG::* aMarker)
+{
+ return ResolveFragmentOrURL(aFrame, &(aFrame->StyleSVG()->*aMarker));
+}
--- a/layout/svg/nsSVGEffects.h
+++ b/layout/svg/nsSVGEffects.h
@@ -587,11 +587,17 @@ public:
const mozilla::FramePropertyDescriptor<nsSVGPaintingProperty>* aProperty);
/**
* Get an nsSVGPaintingProperty for the frame for that URI, creating a fresh
* one if necessary
*/
static nsSVGPaintingProperty *
GetPaintingPropertyForURI(nsIURI *aURI, nsIFrame *aFrame,
URIObserverHashtablePropertyDescriptor aProp);
+
+ /**
+ * A helper function to resolve marker's URL.
+ */
+ static already_AddRefed<nsIURI>
+ GetMarkerURI(nsIFrame* aFrame, FragmentOrURL nsStyleSVG::* aMarker);
};
#endif /*NSSVGEFFECTS_H_*/
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -709,25 +709,30 @@ nsSVGPathGeometryFrame::GetCanvasTM()
}
nsSVGPathGeometryFrame::MarkerProperties
nsSVGPathGeometryFrame::GetMarkerProperties(nsSVGPathGeometryFrame *aFrame)
{
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
MarkerProperties result;
- const nsStyleSVG *style = aFrame->StyleSVG();
+ nsCOMPtr<nsIURI> markerURL =
+ nsSVGEffects::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerStart);
result.mMarkerStart =
- nsSVGEffects::GetMarkerProperty(style->mMarkerStart, aFrame,
+ nsSVGEffects::GetMarkerProperty(markerURL, aFrame,
nsSVGEffects::MarkerBeginProperty());
+
+ markerURL = nsSVGEffects::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerMid);
result.mMarkerMid =
- nsSVGEffects::GetMarkerProperty(style->mMarkerMid, aFrame,
+ nsSVGEffects::GetMarkerProperty(markerURL, aFrame,
nsSVGEffects::MarkerMiddleProperty());
+
+ markerURL = nsSVGEffects::GetMarkerURI(aFrame, &nsStyleSVG::mMarkerEnd);
result.mMarkerEnd =
- nsSVGEffects::GetMarkerProperty(style->mMarkerEnd, aFrame,
+ nsSVGEffects::GetMarkerProperty(markerURL, aFrame,
nsSVGEffects::MarkerEndProperty());
return result;
}
nsSVGMarkerFrame *
nsSVGPathGeometryFrame::MarkerProperties::GetMarkerStartFrame()
{
if (!mMarkerStart)