summaryrefslogtreecommitdiffstats
path: root/accessible/base/AccAttributes.h
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/base/AccAttributes.h')
-rw-r--r--accessible/base/AccAttributes.h294
1 files changed, 294 insertions, 0 deletions
diff --git a/accessible/base/AccAttributes.h b/accessible/base/AccAttributes.h
new file mode 100644
index 0000000000..6ee78aaaa0
--- /dev/null
+++ b/accessible/base/AccAttributes.h
@@ -0,0 +1,294 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef AccAttributes_h_
+#define AccAttributes_h_
+
+#include "mozilla/ServoStyleConsts.h"
+#include "mozilla/a11y/AccGroupInfo.h"
+#include "mozilla/Variant.h"
+#include "nsTHashMap.h"
+#include "nsAtom.h"
+#include "nsStringFwd.h"
+#include "mozilla/gfx/Matrix.h"
+
+class nsVariant;
+
+namespace IPC {
+template <typename T>
+struct ParamTraits;
+} // namespace IPC
+
+namespace mozilla {
+
+namespace dom {
+class Element;
+}
+
+namespace a11y {
+
+struct FontSize {
+ int32_t mValue;
+
+ bool operator==(const FontSize& aOther) const {
+ return mValue == aOther.mValue;
+ }
+
+ bool operator!=(const FontSize& aOther) const {
+ return mValue != aOther.mValue;
+ }
+};
+
+struct Color {
+ nscolor mValue;
+
+ bool operator==(const Color& aOther) const { return mValue == aOther.mValue; }
+
+ bool operator!=(const Color& aOther) const { return mValue != aOther.mValue; }
+};
+
+// A special type. If an entry has a value of this type, it instructs the
+// target instance of an Update to remove the entry with the same key value.
+struct DeleteEntry {
+ DeleteEntry() : mValue(true) {}
+ bool mValue;
+
+ bool operator==(const DeleteEntry& aOther) const { return true; }
+
+ bool operator!=(const DeleteEntry& aOther) const { return false; }
+};
+
+class AccAttributes {
+ // Warning! An AccAttributes can contain another AccAttributes. This is
+ // intended for object and text attributes. However, the nested
+ // AccAttributes should never itself contain another AccAttributes, nor
+ // should it create a cycle. We don't do cycle collection here for
+ // performance reasons, so violating this rule will cause leaks!
+ using AttrValueType =
+ Variant<bool, float, double, int32_t, RefPtr<nsAtom>, nsTArray<int32_t>,
+ CSSCoord, FontSize, Color, DeleteEntry, UniquePtr<nsString>,
+ RefPtr<AccAttributes>, uint64_t, UniquePtr<AccGroupInfo>,
+ UniquePtr<gfx::Matrix4x4>, nsTArray<uint64_t>>;
+ static_assert(sizeof(AttrValueType) <= 16);
+ using AtomVariantMap = nsTHashMap<nsRefPtrHashKey<nsAtom>, AttrValueType>;
+
+ protected:
+ ~AccAttributes() = default;
+
+ public:
+ AccAttributes() = default;
+ AccAttributes(const AccAttributes&) = delete;
+ AccAttributes& operator=(const AccAttributes&) = delete;
+
+ NS_INLINE_DECL_REFCOUNTING(mozilla::a11y::AccAttributes)
+
+ template <typename T>
+ void SetAttribute(nsAtom* aAttrName, T&& aAttrValue) {
+ using ValType =
+ std::remove_const_t<std::remove_reference_t<decltype(aAttrValue)>>;
+ if constexpr (std::is_convertible_v<ValType, nsString>) {
+ static_assert(std::is_rvalue_reference_v<decltype(aAttrValue)>,
+ "Please only move strings into this function. To make a "
+ "copy, use SetAttributeStringCopy.");
+ UniquePtr<nsString> value = MakeUnique<nsString>(std::move(aAttrValue));
+ mData.InsertOrUpdate(aAttrName, AsVariant(std::move(value)));
+ } else if constexpr (std::is_same_v<ValType, gfx::Matrix4x4>) {
+ UniquePtr<gfx::Matrix4x4> value = MakeUnique<gfx::Matrix4x4>(aAttrValue);
+ mData.InsertOrUpdate(aAttrName, AsVariant(std::move(value)));
+ } else if constexpr (std::is_same_v<ValType, AccGroupInfo*>) {
+ UniquePtr<AccGroupInfo> value(aAttrValue);
+ mData.InsertOrUpdate(aAttrName, AsVariant(std::move(value)));
+ } else if constexpr (std::is_convertible_v<ValType, nsAtom*>) {
+ mData.InsertOrUpdate(aAttrName, AsVariant(RefPtr<nsAtom>(aAttrValue)));
+ } else {
+ mData.InsertOrUpdate(aAttrName, AsVariant(std::forward<T>(aAttrValue)));
+ }
+ }
+
+ void SetAttributeStringCopy(nsAtom* aAttrName, nsString aAttrValue) {
+ SetAttribute(aAttrName, std::move(aAttrValue));
+ }
+
+ template <typename T>
+ Maybe<const T&> GetAttribute(nsAtom* aAttrName) const {
+ if (auto value = mData.Lookup(aAttrName)) {
+ if constexpr (std::is_same_v<nsString, T>) {
+ if (value->is<UniquePtr<nsString>>()) {
+ const T& val = *(value->as<UniquePtr<nsString>>().get());
+ return SomeRef(val);
+ }
+ } else if constexpr (std::is_same_v<gfx::Matrix4x4, T>) {
+ if (value->is<UniquePtr<gfx::Matrix4x4>>()) {
+ const T& val = *(value->as<UniquePtr<gfx::Matrix4x4>>());
+ return SomeRef(val);
+ }
+ } else {
+ if (value->is<T>()) {
+ const T& val = value->as<T>();
+ return SomeRef(val);
+ }
+ }
+ }
+ return Nothing();
+ }
+
+ template <typename T>
+ RefPtr<const T> GetAttributeRefPtr(nsAtom* aAttrName) const {
+ if (auto value = mData.Lookup(aAttrName)) {
+ if (value->is<RefPtr<T>>()) {
+ RefPtr<const T> ref = value->as<RefPtr<T>>();
+ return ref;
+ }
+ }
+ return nullptr;
+ }
+
+ template <typename T>
+ Maybe<T&> GetMutableAttribute(nsAtom* aAttrName) const {
+ static_assert(std::is_same_v<nsTArray<int32_t>, T> ||
+ std::is_same_v<nsTArray<uint64_t>, T>,
+ "Only arrays should be mutable attributes");
+ if (auto value = mData.Lookup(aAttrName)) {
+ if (value->is<T>()) {
+ T& val = value->as<T>();
+ return SomeRef(val);
+ }
+ }
+ return Nothing();
+ }
+
+ // Get stringified value
+ bool GetAttribute(nsAtom* aAttrName, nsAString& aAttrValue) const;
+
+ bool HasAttribute(nsAtom* aAttrName) const {
+ return mData.Contains(aAttrName);
+ }
+
+ bool Remove(nsAtom* aAttrName) { return mData.Remove(aAttrName); }
+
+ uint32_t Count() const { return mData.Count(); }
+
+ // Update one instance with the entries in another. The supplied AccAttributes
+ // will be emptied.
+ void Update(AccAttributes* aOther);
+
+ /**
+ * Return true if all the attributes in this instance are equal to all the
+ * attributes in another instance.
+ */
+ bool Equal(const AccAttributes* aOther) const;
+
+ /**
+ * Copy attributes from this instance to another instance.
+ * This should only be used in very specific cases; e.g. merging two sets of
+ * cached attributes without modifying the cache. It can only copy simple
+ * value types; e.g. it can't copy array values. Attempting to copy an
+ * AccAttributes with uncopyable values will cause an assertion.
+ */
+ void CopyTo(AccAttributes* aDest) const;
+
+ // An entry class for our iterator.
+ class Entry {
+ public:
+ Entry(nsAtom* aAttrName, const AttrValueType* aAttrValue)
+ : mName(aAttrName), mValue(aAttrValue) {}
+
+ nsAtom* Name() const { return mName; }
+
+ template <typename T>
+ Maybe<const T&> Value() const {
+ if constexpr (std::is_same_v<nsString, T>) {
+ if (mValue->is<UniquePtr<nsString>>()) {
+ const T& val = *(mValue->as<UniquePtr<nsString>>().get());
+ return SomeRef(val);
+ }
+ } else if constexpr (std::is_same_v<gfx::Matrix4x4, T>) {
+ if (mValue->is<UniquePtr<gfx::Matrix4x4>>()) {
+ const T& val = *(mValue->as<UniquePtr<gfx::Matrix4x4>>());
+ return SomeRef(val);
+ }
+ } else {
+ if (mValue->is<T>()) {
+ const T& val = mValue->as<T>();
+ return SomeRef(val);
+ }
+ }
+ return Nothing();
+ }
+
+ void NameAsString(nsString& aName) const {
+ mName->ToString(aName);
+ if (StringBeginsWith(aName, u"aria-"_ns)) {
+ // Found 'aria-'
+ aName.ReplaceLiteral(0, 5, u"");
+ }
+ }
+
+ void ValueAsString(nsAString& aValueString) const {
+ StringFromValueAndName(mName, *mValue, aValueString);
+ }
+
+ // Size of the pair in the hash table.
+ size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf);
+
+ private:
+ nsAtom* mName;
+ const AttrValueType* mValue;
+
+ friend class AccAttributes;
+ };
+
+ class Iterator {
+ public:
+ explicit Iterator(AtomVariantMap::const_iterator aIter)
+ : mHashIterator(aIter) {}
+
+ Iterator() = delete;
+ Iterator(const Iterator&) = delete;
+ Iterator& operator=(const Iterator&) = delete;
+
+ bool operator!=(const Iterator& aOther) const {
+ return mHashIterator != aOther.mHashIterator;
+ }
+
+ Iterator& operator++() {
+ mHashIterator++;
+ return *this;
+ }
+
+ Entry operator*() const {
+ auto& entry = *mHashIterator;
+ return Entry(entry.GetKey(), &entry.GetData());
+ }
+
+ private:
+ AtomVariantMap::const_iterator mHashIterator;
+ };
+
+ friend class Iterator;
+
+ Iterator begin() const { return Iterator(mData.begin()); }
+ Iterator end() const { return Iterator(mData.end()); }
+
+#ifdef A11Y_LOG
+ static void DebugPrint(const char* aPrefix, const AccAttributes& aAttributes);
+#endif
+
+ size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf);
+
+ private:
+ static void StringFromValueAndName(nsAtom* aAttrName,
+ const AttrValueType& aValue,
+ nsAString& aValueString);
+
+ AtomVariantMap mData;
+
+ friend struct IPC::ParamTraits<AccAttributes*>;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif