AnimatedPropertyIDSet.h (7387B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_AnimatedPropertyIDSet_h 8 #define mozilla_AnimatedPropertyIDSet_h 9 10 #include "CSSPropertyId.h" 11 #include "mozilla/ServoBindings.h" 12 #include "nsCSSPropertyIDSet.h" 13 #include "nsTHashSet.h" 14 15 namespace mozilla { 16 17 class AnimatedPropertyIDSet { 18 public: 19 using CustomNameSet = nsTHashSet<RefPtr<nsAtom>>; 20 21 AnimatedPropertyIDSet() = default; 22 AnimatedPropertyIDSet(AnimatedPropertyIDSet&& aOther) = default; 23 AnimatedPropertyIDSet(nsCSSPropertyIDSet&& aIDs, CustomNameSet&& aNames) 24 : mIDs(std::move(aIDs)), mCustomNames(std::move(aNames)) {} 25 26 AnimatedPropertyIDSet& operator=(AnimatedPropertyIDSet&& aRhs) { 27 MOZ_ASSERT(&aRhs != this); 28 this->~AnimatedPropertyIDSet(); 29 new (this) AnimatedPropertyIDSet(std::move(aRhs)); 30 return *this; 31 } 32 33 void AddProperty(const CSSPropertyId& aProperty) { 34 if (aProperty.IsCustom()) { 35 mCustomNames.Insert(aProperty.mCustomName); 36 } else { 37 mIDs.AddProperty(aProperty.mId); 38 } 39 } 40 41 void RemoveProperty(const CSSPropertyId& aProperty) { 42 if (aProperty.IsCustom()) { 43 mCustomNames.Remove(aProperty.mCustomName); 44 } else { 45 mIDs.RemoveProperty(aProperty.mId); 46 } 47 } 48 49 bool HasProperty(const CSSPropertyId& aProperty) const { 50 if (aProperty.IsCustom()) { 51 return mCustomNames.Contains(aProperty.mCustomName); 52 } 53 return mIDs.HasProperty(aProperty.mId); 54 } 55 56 bool Intersects(const nsCSSPropertyIDSet& aIDs) const { 57 return mIDs.Intersects(aIDs); 58 } 59 60 bool IsSubsetOf(const AnimatedPropertyIDSet& aOther) const { 61 if (!mIDs.IsSubsetOf(aOther.mIDs) || 62 mCustomNames.Count() > aOther.mCustomNames.Count()) { 63 return false; 64 } 65 for (const auto& name : mCustomNames) { 66 if (!aOther.mCustomNames.Contains(name)) { 67 return false; 68 } 69 } 70 return true; 71 } 72 73 bool IsEmpty() const { return mIDs.IsEmpty() && mCustomNames.IsEmpty(); } 74 75 void AddProperties(const AnimatedPropertyIDSet& aOther) { 76 mIDs |= aOther.mIDs; 77 for (const auto& name : aOther.mCustomNames) { 78 mCustomNames.Insert(name); 79 } 80 } 81 82 // Returns a new nsCSSPropertyIDSet with all properties that are both in this 83 // set and |aOther|. 84 nsCSSPropertyIDSet Intersect(const nsCSSPropertyIDSet& aOther) const { 85 return mIDs.Intersect(aOther); 86 } 87 88 // Returns a new AnimatedPropertyIDSet with all properties that are both in 89 // this set and |aOther|. 90 AnimatedPropertyIDSet Intersect(const AnimatedPropertyIDSet& aOther) const { 91 nsCSSPropertyIDSet ids = mIDs.Intersect(aOther.mIDs); 92 CustomNameSet names; 93 for (const auto& name : mCustomNames) { 94 if (!aOther.mCustomNames.Contains(name)) { 95 continue; 96 } 97 names.Insert(name); 98 } 99 return AnimatedPropertyIDSet(std::move(ids), std::move(names)); 100 } 101 102 // Returns a new AnimatedPropertyIDSet with all properties that are in either 103 // this set or |aOther| but not both. 104 AnimatedPropertyIDSet Xor(const AnimatedPropertyIDSet& aOther) const { 105 nsCSSPropertyIDSet ids = mIDs.Xor(aOther.mIDs); 106 CustomNameSet names; 107 for (const auto& name : mCustomNames) { 108 if (aOther.mCustomNames.Contains(name)) { 109 continue; 110 } 111 names.Insert(name); 112 } 113 114 for (const auto& name : aOther.mCustomNames) { 115 if (mCustomNames.Contains(name)) { 116 continue; 117 } 118 names.Insert(name); 119 } 120 return AnimatedPropertyIDSet(std::move(ids), std::move(names)); 121 } 122 123 // Iterator for use in range-based for loops 124 class Iterator { 125 public: 126 Iterator(Iterator&& aOther) 127 : mPropertySet(aOther.mPropertySet), 128 mIDIterator(std::move(aOther.mIDIterator)), 129 mCustomNameIterator(std::move(aOther.mCustomNameIterator)), 130 mPropertyId(eCSSProperty_UNKNOWN) {} 131 Iterator() = delete; 132 Iterator(const Iterator&) = delete; 133 Iterator& operator=(const Iterator&) = delete; 134 Iterator& operator=(const Iterator&&) = delete; 135 136 static Iterator BeginIterator(const AnimatedPropertyIDSet& aPropertySet) { 137 return Iterator(aPropertySet, aPropertySet.mIDs.begin(), 138 aPropertySet.mCustomNames.begin()); 139 } 140 141 static Iterator EndIterator(const AnimatedPropertyIDSet& aPropertySet) { 142 return Iterator(aPropertySet, aPropertySet.mIDs.end(), 143 aPropertySet.mCustomNames.end()); 144 } 145 146 bool operator!=(const Iterator& aOther) const { 147 return mIDIterator != aOther.mIDIterator || 148 mCustomNameIterator != aOther.mCustomNameIterator; 149 } 150 151 Iterator& operator++() { 152 MOZ_ASSERT(mIDIterator != mPropertySet.mIDs.end() || 153 mCustomNameIterator != mPropertySet.mCustomNames.end(), 154 "Should not iterate beyond end"); 155 if (mIDIterator != mPropertySet.mIDs.end()) { 156 ++mIDIterator; 157 } else { 158 ++mCustomNameIterator; 159 } 160 return *this; 161 } 162 163 CSSPropertyId operator*() { 164 if (mIDIterator != mPropertySet.mIDs.end()) { 165 mPropertyId.mId = *mIDIterator; 166 mPropertyId.mCustomName = nullptr; 167 } else if (mCustomNameIterator != mPropertySet.mCustomNames.end()) { 168 mPropertyId.mId = eCSSPropertyExtra_variable; 169 mPropertyId.mCustomName = *mCustomNameIterator; 170 } else { 171 MOZ_ASSERT_UNREACHABLE("Should not dereference beyond end"); 172 mPropertyId.mId = eCSSProperty_UNKNOWN; 173 mPropertyId.mCustomName = nullptr; 174 } 175 return mPropertyId; 176 } 177 178 private: 179 Iterator(const AnimatedPropertyIDSet& aPropertySet, 180 nsCSSPropertyIDSet::Iterator aIDIterator, 181 CustomNameSet::const_iterator aCustomNameIterator) 182 : mPropertySet(aPropertySet), 183 mIDIterator(std::move(aIDIterator)), 184 mCustomNameIterator(std::move(aCustomNameIterator)), 185 mPropertyId(eCSSProperty_UNKNOWN) {} 186 187 const AnimatedPropertyIDSet& mPropertySet; 188 nsCSSPropertyIDSet::Iterator mIDIterator; 189 CustomNameSet::const_iterator mCustomNameIterator; 190 CSSPropertyId mPropertyId; 191 }; 192 193 Iterator begin() const { return Iterator::BeginIterator(*this); } 194 Iterator end() const { return Iterator::EndIterator(*this); } 195 196 private: 197 AnimatedPropertyIDSet(const AnimatedPropertyIDSet&) = delete; 198 AnimatedPropertyIDSet& operator=(const AnimatedPropertyIDSet&) = delete; 199 200 nsCSSPropertyIDSet mIDs; 201 CustomNameSet mCustomNames; 202 }; 203 204 // A wrapper to support the inversion of AnimatedPropertyIDSet. 205 // 206 // We are using this struct (for convenience) to check if we should skip the 207 // AnimatedPropertyIDs when composing an animation rule, on either 208 // CascadeLevel::Animations or CascadeLevel::Tranistions. 209 struct InvertibleAnimatedPropertyIDSet { 210 const AnimatedPropertyIDSet* mSet = nullptr; 211 bool mIsInverted = false; 212 213 void Setup(const AnimatedPropertyIDSet* aSet, bool aIsInverted) { 214 mSet = aSet; 215 mIsInverted = aIsInverted; 216 } 217 218 bool HasProperty(const CSSPropertyId& aProperty) const { 219 return mSet && mIsInverted != mSet->HasProperty(aProperty); 220 } 221 }; 222 223 } // namespace mozilla 224 225 #endif // mozilla_AnimatedPropertyIDSet_h