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"
13 #include "nsStringFwd.h"
14 #include "mozilla/gfx/Matrix.h"
34 bool operator==(const FontSize
& aOther
) const {
35 return mValue
== aOther
.mValue
;
38 bool operator!=(const FontSize
& aOther
) const {
39 return mValue
!= aOther
.mValue
;
46 bool operator==(const Color
& aOther
) const { return mValue
== aOther
.mValue
; }
48 bool operator!=(const Color
& aOther
) const { return mValue
!= aOther
.mValue
; }
51 // A special type. If an entry has a value of this type, it instructs the
52 // target instance of an Update to remove the entry with the same key value.
54 DeleteEntry() : mValue(true) {}
57 bool operator==(const DeleteEntry
& aOther
) const { return true; }
59 bool operator!=(const DeleteEntry
& aOther
) const { return false; }
63 // Warning! An AccAttributes can contain another AccAttributes. This is
64 // intended for object and text attributes. However, the nested
65 // AccAttributes should never itself contain another AccAttributes, nor
66 // should it create a cycle. We don't do cycle collection here for
67 // performance reasons, so violating this rule will cause leaks!
69 Variant
<bool, float, double, int32_t, RefPtr
<nsAtom
>, nsTArray
<int32_t>,
70 CSSCoord
, FontSize
, Color
, DeleteEntry
, UniquePtr
<nsString
>,
71 RefPtr
<AccAttributes
>, uint64_t, UniquePtr
<AccGroupInfo
>,
72 UniquePtr
<gfx::Matrix4x4
>, nsTArray
<uint64_t>>;
73 static_assert(sizeof(AttrValueType
) <= 16);
74 using AtomVariantMap
= nsTHashMap
<RefPtr
<nsAtom
>, AttrValueType
>;
77 ~AccAttributes() = default;
80 AccAttributes() = default;
81 AccAttributes(const AccAttributes
&) = delete;
82 AccAttributes
& operator=(const AccAttributes
&) = delete;
84 NS_INLINE_DECL_REFCOUNTING(mozilla::a11y::AccAttributes
)
87 void SetAttribute(nsAtom
* aAttrName
, T
&& aAttrValue
) {
89 std::remove_const_t
<std::remove_reference_t
<decltype(aAttrValue
)>>;
90 if constexpr (std::is_convertible_v
<ValType
, nsString
>) {
91 static_assert(std::is_rvalue_reference_v
<decltype(aAttrValue
)>,
92 "Please only move strings into this function. To make a "
93 "copy, use SetAttributeStringCopy.");
94 UniquePtr
<nsString
> value
= MakeUnique
<nsString
>(std::move(aAttrValue
));
95 mData
.InsertOrUpdate(aAttrName
, AsVariant(std::move(value
)));
96 } else if constexpr (std::is_same_v
<ValType
, gfx::Matrix4x4
>) {
97 UniquePtr
<gfx::Matrix4x4
> value
= MakeUnique
<gfx::Matrix4x4
>(aAttrValue
);
98 mData
.InsertOrUpdate(aAttrName
, AsVariant(std::move(value
)));
99 } else if constexpr (std::is_same_v
<ValType
, AccGroupInfo
*>) {
100 UniquePtr
<AccGroupInfo
> value(aAttrValue
);
101 mData
.InsertOrUpdate(aAttrName
, AsVariant(std::move(value
)));
102 } else if constexpr (std::is_convertible_v
<ValType
, nsAtom
*>) {
103 mData
.InsertOrUpdate(aAttrName
, AsVariant(RefPtr
<nsAtom
>(aAttrValue
)));
105 mData
.InsertOrUpdate(aAttrName
, AsVariant(std::forward
<T
>(aAttrValue
)));
109 void SetAttributeStringCopy(nsAtom
* aAttrName
, nsString aAttrValue
) {
110 SetAttribute(aAttrName
, std::move(aAttrValue
));
113 template <typename T
>
114 Maybe
<const T
&> GetAttribute(nsAtom
* aAttrName
) const {
115 if (auto value
= mData
.Lookup(aAttrName
)) {
116 if constexpr (std::is_same_v
<nsString
, T
>) {
117 if (value
->is
<UniquePtr
<nsString
>>()) {
118 const T
& val
= *(value
->as
<UniquePtr
<nsString
>>().get());
121 } else if constexpr (std::is_same_v
<gfx::Matrix4x4
, T
>) {
122 if (value
->is
<UniquePtr
<gfx::Matrix4x4
>>()) {
123 const T
& val
= *(value
->as
<UniquePtr
<gfx::Matrix4x4
>>());
127 if (value
->is
<T
>()) {
128 const T
& val
= value
->as
<T
>();
136 template <typename T
>
137 RefPtr
<const T
> GetAttributeRefPtr(nsAtom
* aAttrName
) const {
138 if (auto value
= mData
.Lookup(aAttrName
)) {
139 if (value
->is
<RefPtr
<T
>>()) {
140 RefPtr
<const T
> ref
= value
->as
<RefPtr
<T
>>();
147 template <typename T
>
148 Maybe
<T
&> GetMutableAttribute(nsAtom
* aAttrName
) const {
149 static_assert(std::is_same_v
<nsTArray
<int32_t>, T
> ||
150 std::is_same_v
<nsTArray
<uint64_t>, T
>,
151 "Only arrays should be mutable attributes");
152 if (auto value
= mData
.Lookup(aAttrName
)) {
153 if (value
->is
<T
>()) {
154 T
& val
= value
->as
<T
>();
161 // Get stringified value
162 bool GetAttribute(nsAtom
* aAttrName
, nsAString
& aAttrValue
) const;
164 bool HasAttribute(nsAtom
* aAttrName
) const {
165 return mData
.Contains(aAttrName
);
168 bool Remove(nsAtom
* aAttrName
) { return mData
.Remove(aAttrName
); }
170 uint32_t Count() const { return mData
.Count(); }
172 // Update one instance with the entries in another. The supplied AccAttributes
174 void Update(AccAttributes
* aOther
);
177 * Return true if all the attributes in this instance are equal to all the
178 * attributes in another instance.
180 bool Equal(const AccAttributes
* aOther
) const;
183 * Copy attributes from this instance to another instance.
184 * This should only be used in very specific cases; e.g. merging two sets of
185 * cached attributes without modifying the cache. It can only copy simple
186 * value types; e.g. it can't copy array values. Attempting to copy an
187 * AccAttributes with uncopyable values will cause an assertion.
189 void CopyTo(AccAttributes
* aDest
) const;
191 // An entry class for our iterator.
194 Entry(nsAtom
* aAttrName
, const AttrValueType
* aAttrValue
)
195 : mName(aAttrName
), mValue(aAttrValue
) {}
197 nsAtom
* Name() const { return mName
; }
199 template <typename T
>
200 Maybe
<const T
&> Value() const {
201 if constexpr (std::is_same_v
<nsString
, T
>) {
202 if (mValue
->is
<UniquePtr
<nsString
>>()) {
203 const T
& val
= *(mValue
->as
<UniquePtr
<nsString
>>().get());
206 } else if constexpr (std::is_same_v
<gfx::Matrix4x4
, T
>) {
207 if (mValue
->is
<UniquePtr
<gfx::Matrix4x4
>>()) {
208 const T
& val
= *(mValue
->as
<UniquePtr
<gfx::Matrix4x4
>>());
212 if (mValue
->is
<T
>()) {
213 const T
& val
= mValue
->as
<T
>();
220 void NameAsString(nsString
& aName
) const {
221 mName
->ToString(aName
);
222 if (StringBeginsWith(aName
, u
"aria-"_ns
)) {
224 aName
.ReplaceLiteral(0, 5, u
"");
228 void ValueAsString(nsAString
& aValueString
) const {
229 StringFromValueAndName(mName
, *mValue
, aValueString
);
232 // Size of the pair in the hash table.
233 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf
);
237 const AttrValueType
* mValue
;
239 friend class AccAttributes
;
244 explicit Iterator(AtomVariantMap::const_iterator aIter
)
245 : mHashIterator(aIter
) {}
248 Iterator(const Iterator
&) = delete;
249 Iterator
& operator=(const Iterator
&) = delete;
251 bool operator!=(const Iterator
& aOther
) const {
252 return mHashIterator
!= aOther
.mHashIterator
;
255 Iterator
& operator++() {
260 Entry
operator*() const {
261 auto& entry
= *mHashIterator
;
262 return Entry(entry
.GetKey(), &entry
.GetData());
266 AtomVariantMap::const_iterator mHashIterator
;
269 friend class Iterator
;
271 Iterator
begin() const { return Iterator(mData
.begin()); }
272 Iterator
end() const { return Iterator(mData
.end()); }
275 static void DebugPrint(const char* aPrefix
, const AccAttributes
& aAttributes
);
278 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
);
281 static void StringFromValueAndName(nsAtom
* aAttrName
,
282 const AttrValueType
& aValue
,
283 nsAString
& aValueString
);
285 AtomVariantMap mData
;
287 friend struct IPC::ParamTraits
<AccAttributes
*>;
291 } // namespace mozilla