1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef AccAttributes_h_
7 #define AccAttributes_h_
9 #include "mozilla/ServoStyleConsts.h"
10 #include "mozilla/a11y/AccGroupInfo.h"
11 #include "mozilla/Variant.h"
12 #include "nsTHashMap.h"
14 #include "nsStringFwd.h"
15 #include "mozilla/gfx/Matrix.h"
35 bool operator==(const FontSize
& aOther
) const {
36 return mValue
== aOther
.mValue
;
39 bool operator!=(const FontSize
& aOther
) const {
40 return mValue
!= aOther
.mValue
;
47 bool operator==(const Color
& aOther
) const { return mValue
== aOther
.mValue
; }
49 bool operator!=(const Color
& aOther
) const { return mValue
!= aOther
.mValue
; }
52 // A special type. If an entry has a value of this type, it instructs the
53 // target instance of an Update to remove the entry with the same key value.
55 DeleteEntry() : mValue(true) {}
58 bool operator==(const DeleteEntry
& aOther
) const { return true; }
60 bool operator!=(const DeleteEntry
& aOther
) const { return false; }
64 // Warning! An AccAttributes can contain another AccAttributes. This is
65 // intended for object and text attributes. However, the nested
66 // AccAttributes should never itself contain another AccAttributes, nor
67 // should it create a cycle. We don't do cycle collection here for
68 // performance reasons, so violating this rule will cause leaks!
70 Variant
<bool, float, double, int32_t, RefPtr
<nsAtom
>, nsTArray
<int32_t>,
71 CSSCoord
, FontSize
, Color
, DeleteEntry
, UniquePtr
<nsString
>,
72 RefPtr
<AccAttributes
>, uint64_t, UniquePtr
<AccGroupInfo
>,
73 UniquePtr
<gfx::Matrix4x4
>, nsTArray
<uint64_t>>;
74 static_assert(sizeof(AttrValueType
) <= 16);
75 using AtomVariantMap
= nsTHashMap
<nsRefPtrHashKey
<nsAtom
>, AttrValueType
>;
78 ~AccAttributes() = default;
81 AccAttributes() = default;
82 AccAttributes(const AccAttributes
&) = delete;
83 AccAttributes
& operator=(const AccAttributes
&) = delete;
85 NS_INLINE_DECL_REFCOUNTING(mozilla::a11y::AccAttributes
)
88 void SetAttribute(nsAtom
* aAttrName
, T
&& aAttrValue
) {
90 std::remove_const_t
<std::remove_reference_t
<decltype(aAttrValue
)>>;
91 if constexpr (std::is_convertible_v
<ValType
, nsString
>) {
92 static_assert(std::is_rvalue_reference_v
<decltype(aAttrValue
)>,
93 "Please only move strings into this function. To make a "
94 "copy, use SetAttributeStringCopy.");
95 UniquePtr
<nsString
> value
= MakeUnique
<nsString
>(std::move(aAttrValue
));
96 mData
.InsertOrUpdate(aAttrName
, AsVariant(std::move(value
)));
97 } else if constexpr (std::is_same_v
<ValType
, gfx::Matrix4x4
>) {
98 UniquePtr
<gfx::Matrix4x4
> value
= MakeUnique
<gfx::Matrix4x4
>(aAttrValue
);
99 mData
.InsertOrUpdate(aAttrName
, AsVariant(std::move(value
)));
100 } else if constexpr (std::is_same_v
<ValType
, AccGroupInfo
*>) {
101 UniquePtr
<AccGroupInfo
> value(aAttrValue
);
102 mData
.InsertOrUpdate(aAttrName
, AsVariant(std::move(value
)));
103 } else if constexpr (std::is_convertible_v
<ValType
, nsAtom
*>) {
104 mData
.InsertOrUpdate(aAttrName
, AsVariant(RefPtr
<nsAtom
>(aAttrValue
)));
106 mData
.InsertOrUpdate(aAttrName
, AsVariant(std::forward
<T
>(aAttrValue
)));
110 void SetAttributeStringCopy(nsAtom
* aAttrName
, nsString aAttrValue
) {
111 SetAttribute(aAttrName
, std::move(aAttrValue
));
114 template <typename T
>
115 Maybe
<const T
&> GetAttribute(nsAtom
* aAttrName
) const {
116 if (auto value
= mData
.Lookup(aAttrName
)) {
117 if constexpr (std::is_same_v
<nsString
, T
>) {
118 if (value
->is
<UniquePtr
<nsString
>>()) {
119 const T
& val
= *(value
->as
<UniquePtr
<nsString
>>().get());
122 } else if constexpr (std::is_same_v
<gfx::Matrix4x4
, T
>) {
123 if (value
->is
<UniquePtr
<gfx::Matrix4x4
>>()) {
124 const T
& val
= *(value
->as
<UniquePtr
<gfx::Matrix4x4
>>());
128 if (value
->is
<T
>()) {
129 const T
& val
= value
->as
<T
>();
137 template <typename T
>
138 RefPtr
<const T
> GetAttributeRefPtr(nsAtom
* aAttrName
) const {
139 if (auto value
= mData
.Lookup(aAttrName
)) {
140 if (value
->is
<RefPtr
<T
>>()) {
141 RefPtr
<const T
> ref
= value
->as
<RefPtr
<T
>>();
148 template <typename T
>
149 Maybe
<T
&> GetMutableAttribute(nsAtom
* aAttrName
) const {
150 static_assert(std::is_same_v
<nsTArray
<int32_t>, T
> ||
151 std::is_same_v
<nsTArray
<uint64_t>, T
>,
152 "Only arrays should be mutable attributes");
153 if (auto value
= mData
.Lookup(aAttrName
)) {
154 if (value
->is
<T
>()) {
155 T
& val
= value
->as
<T
>();
162 // Get stringified value
163 bool GetAttribute(nsAtom
* aAttrName
, nsAString
& aAttrValue
) const;
165 bool HasAttribute(nsAtom
* aAttrName
) const {
166 return mData
.Contains(aAttrName
);
169 bool Remove(nsAtom
* aAttrName
) { return mData
.Remove(aAttrName
); }
171 uint32_t Count() const { return mData
.Count(); }
173 // Update one instance with the entries in another. The supplied AccAttributes
175 void Update(AccAttributes
* aOther
);
178 * Return true if all the attributes in this instance are equal to all the
179 * attributes in another instance.
181 bool Equal(const AccAttributes
* aOther
) const;
184 * Copy attributes from this instance to another instance.
185 * This should only be used in very specific cases; e.g. merging two sets of
186 * cached attributes without modifying the cache. It can only copy simple
187 * value types; e.g. it can't copy array values. Attempting to copy an
188 * AccAttributes with uncopyable values will cause an assertion.
190 void CopyTo(AccAttributes
* aDest
) const;
192 // An entry class for our iterator.
195 Entry(nsAtom
* aAttrName
, const AttrValueType
* aAttrValue
)
196 : mName(aAttrName
), mValue(aAttrValue
) {}
198 nsAtom
* Name() const { return mName
; }
200 template <typename T
>
201 Maybe
<const T
&> Value() const {
202 if constexpr (std::is_same_v
<nsString
, T
>) {
203 if (mValue
->is
<UniquePtr
<nsString
>>()) {
204 const T
& val
= *(mValue
->as
<UniquePtr
<nsString
>>().get());
207 } else if constexpr (std::is_same_v
<gfx::Matrix4x4
, T
>) {
208 if (mValue
->is
<UniquePtr
<gfx::Matrix4x4
>>()) {
209 const T
& val
= *(mValue
->as
<UniquePtr
<gfx::Matrix4x4
>>());
213 if (mValue
->is
<T
>()) {
214 const T
& val
= mValue
->as
<T
>();
221 void NameAsString(nsString
& aName
) const {
222 mName
->ToString(aName
);
223 if (StringBeginsWith(aName
, u
"aria-"_ns
)) {
225 aName
.ReplaceLiteral(0, 5, u
"");
229 void ValueAsString(nsAString
& aValueString
) const {
230 StringFromValueAndName(mName
, *mValue
, aValueString
);
233 // Size of the pair in the hash table.
234 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf
);
238 const AttrValueType
* mValue
;
240 friend class AccAttributes
;
245 explicit Iterator(AtomVariantMap::const_iterator aIter
)
246 : mHashIterator(aIter
) {}
249 Iterator(const Iterator
&) = delete;
250 Iterator
& operator=(const Iterator
&) = delete;
252 bool operator!=(const Iterator
& aOther
) const {
253 return mHashIterator
!= aOther
.mHashIterator
;
256 Iterator
& operator++() {
261 Entry
operator*() const {
262 auto& entry
= *mHashIterator
;
263 return Entry(entry
.GetKey(), &entry
.GetData());
267 AtomVariantMap::const_iterator mHashIterator
;
270 friend class Iterator
;
272 Iterator
begin() const { return Iterator(mData
.begin()); }
273 Iterator
end() const { return Iterator(mData
.end()); }
276 static void DebugPrint(const char* aPrefix
, const AccAttributes
& aAttributes
);
279 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
);
282 static void StringFromValueAndName(nsAtom
* aAttrName
,
283 const AttrValueType
& aValue
,
284 nsAString
& aValueString
);
286 AtomVariantMap mData
;
288 friend struct IPC::ParamTraits
<AccAttributes
*>;
292 } // namespace mozilla