Bug 1354772 - Part 2. Compute URLValueData::mMightHaveRef when need.
MozReview-Commit-ID: 8t5tKrjB1cz
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -40,16 +40,29 @@ IsLocalRefURL(nsStringBuffer* aString)
// local-ref URL.
return *current == '#';
}
}
return false;
}
+static bool
+MightHaveRef(nsStringBuffer* aString)
+{
+ char16_t* current = static_cast<char16_t*>(aString->Data());
+ for (; *current != '\0'; current++) {
+ if (*current == '#') {
+ return true;
+ }
+ }
+
+ return false;
+}
+
nsCSSValue::nsCSSValue(int32_t aValue, nsCSSUnit aUnit)
: mUnit(aUnit)
{
MOZ_ASSERT(aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
aUnit == eCSSUnit_EnumColor,
"not an int value");
if (aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
aUnit == eCSSUnit_EnumColor) {
@@ -2890,16 +2903,28 @@ css::URLValueData::HasRef() const
nsresult rv = uri->GetRef(ref);
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
return true;
}
return false;
}
+bool
+css::URLValueData::MightHaveRef() const
+{
+ if (mMightHaveRef.isNothing()) {
+ // ::MightHaveRef is O(N), use it only use it only when MightHaveRef is
+ // called.
+ mMightHaveRef.emplace(::MightHaveRef(mString));
+ }
+
+ return mMightHaveRef.value();
+}
+
already_AddRefed<nsIURI>
css::URLValueData::ResolveLocalRef(nsIURI* aURI) const
{
nsCOMPtr<nsIURI> result = GetURI();
if (result && IsLocalRef()) {
nsCString ref;
mURI->GetRef(ref);
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -130,16 +130,24 @@ public:
bool DefinitelyEqualURIsAndPrincipal(const URLValueData& aOther) const;
nsIURI* GetURI() const;
bool IsLocalRef() const;
bool HasRef() const;
+ // This function takes a guess whether the URL has a fragment, by searching
+ // for a hash character. It definitely returns false if we know it can't
+ // have a fragment because it has no hash character.
+ //
+ // MightHaveRef can be used in any thread, whereas HasRef can only be used
+ // in the main thread.
+ bool MightHaveRef() const;
+
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLValueData)
// When matching a url with mIsLocalRef set, resolve it against aURI;
// Otherwise, ignore aURL and return mURL directly.
already_AddRefed<nsIURI> ResolveLocalRef(nsIURI* aURI) const;
already_AddRefed<nsIURI> ResolveLocalRef(nsIContent* aContent) const;
// Serializes mURI as a computed URI value, taking into account mIsLocalRef
@@ -154,16 +162,17 @@ private:
mutable PtrHandle<nsIURI> mURI;
public:
RefPtr<nsStringBuffer> mString;
RefPtr<URLExtraData> mExtraData;
private:
mutable bool mURIResolved;
// mIsLocalRef is set when url starts with a U+0023 number sign(#) character.
mutable Maybe<bool> mIsLocalRef;
+ mutable Maybe<bool> mMightHaveRef;
protected:
virtual ~URLValueData() = default;
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
private:
URLValueData(const URLValueData& aOther) = delete;
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -3023,21 +3023,21 @@ nsStyleImageLayers::Layer::CalcDifferenc
// mask:url(#localMaskID); // The fragment of this URI is an ID of a mask
// // element in local document.
// mask:url(b.svg#viewBoxID); // The fragment of this URI is an ID of a
// // viewbox defined in b.svg.
// That is, if mSourceURI has a fragment, it may link to a SVG mask; If
// not, it "must" not link to a SVG mask.
bool maybeSVGMask = false;
if (mImage.GetURLValue()) {
- maybeSVGMask = mImage.GetURLValue()->HasRef();
+ maybeSVGMask = mImage.GetURLValue()->MightHaveRef();
}
if (!maybeSVGMask && aNewLayer.mImage.GetURLValue()) {
- maybeSVGMask = aNewLayer.mImage.GetURLValue()->HasRef();
+ maybeSVGMask = aNewLayer.mImage.GetURLValue()->MightHaveRef();
}
// Return nsChangeHint_UpdateOverflow if either URI might link to an SVG
// mask.
if (maybeSVGMask) {
// Mask changes require that we update the PreEffectsBBoxProperty,
// which is done during overflow computation.
hint |= nsChangeHint_UpdateOverflow;