Bug 1700051: part 48) Slightly simplify `mozInlineSpellWordUtil::FindRealWordContaini...
[gecko.git] / layout / style / nsCSSPropertyIDSet.h
blob3f1d99cf6089e6b06ed219c5febae7aea4de427e
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /* bit vectors for sets of CSS properties */
7 #ifndef nsCSSPropertyIDSet_h__
8 #define nsCSSPropertyIDSet_h__
10 #include <initializer_list>
11 #include <limits.h> // for CHAR_BIT
12 #include <ostream>
14 #include "mozilla/ArrayUtils.h"
15 // For COMPOSITOR_ANIMATABLE_PROPERTY_LIST and
16 // COMPOSITOR_ANIMATABLE_PROPERTY_LIST_LENGTH
17 #include "mozilla/CompositorAnimatableProperties.h"
18 #include "nsCSSProps.h" // For operator<< for nsCSSPropertyID
19 #include "nsCSSPropertyID.h"
21 /**
22 * nsCSSPropertyIDSet maintains a set of non-shorthand CSS properties. In
23 * other words, for each longhand CSS property we support, it has a bit
24 * for whether that property is in the set.
26 class nsCSSPropertyIDSet {
27 public:
28 nsCSSPropertyIDSet() { Empty(); }
29 // auto-generated copy-constructor OK
31 explicit constexpr nsCSSPropertyIDSet(
32 std::initializer_list<nsCSSPropertyID> aProperties)
33 : mProperties{0} {
34 for (auto property : aProperties) {
35 size_t p = property;
36 mProperties[p / kBitsInChunk] |= property_set_type(1)
37 << (p % kBitsInChunk);
41 void AssertInSetRange(nsCSSPropertyID aProperty) const {
42 NS_ASSERTION(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
43 "out of bounds");
46 // Conversion of aProperty to |size_t| after AssertInSetRange
47 // lets the compiler generate significantly tighter code.
49 void AddProperty(nsCSSPropertyID aProperty) {
50 AssertInSetRange(aProperty);
51 size_t p = aProperty;
52 mProperties[p / kBitsInChunk] |= property_set_type(1) << (p % kBitsInChunk);
55 void RemoveProperty(nsCSSPropertyID aProperty) {
56 AssertInSetRange(aProperty);
57 size_t p = aProperty;
58 mProperties[p / kBitsInChunk] &=
59 ~(property_set_type(1) << (p % kBitsInChunk));
62 bool HasProperty(nsCSSPropertyID aProperty) const {
63 AssertInSetRange(aProperty);
64 size_t p = aProperty;
65 return (mProperties[p / kBitsInChunk] &
66 (property_set_type(1) << (p % kBitsInChunk))) != 0;
69 // Returns an nsCSSPropertyIDSet including all properties that can be run
70 // on the compositor.
71 static constexpr nsCSSPropertyIDSet CompositorAnimatables() {
72 return nsCSSPropertyIDSet(COMPOSITOR_ANIMATABLE_PROPERTY_LIST);
75 static constexpr size_t CompositorAnimatableCount() {
76 return COMPOSITOR_ANIMATABLE_PROPERTY_LIST_LENGTH;
79 static constexpr size_t CompositorAnimatableDisplayItemCount() {
80 // We have 3 individual transforms and 4 motion path properties, and they
81 // also use DisplayItemType::TYPE_TRANSFORM.
82 return COMPOSITOR_ANIMATABLE_PROPERTY_LIST_LENGTH - 7;
85 static constexpr nsCSSPropertyIDSet CSSTransformProperties() {
86 return nsCSSPropertyIDSet{eCSSProperty_transform, eCSSProperty_translate,
87 eCSSProperty_rotate, eCSSProperty_scale};
90 static constexpr nsCSSPropertyIDSet MotionPathProperties() {
91 // FIXME: Bug 1559232: Add offset-position.
92 return nsCSSPropertyIDSet{
93 eCSSProperty_offset_path, eCSSProperty_offset_distance,
94 eCSSProperty_offset_rotate, eCSSProperty_offset_anchor};
97 static constexpr nsCSSPropertyIDSet TransformLikeProperties() {
98 // FIXME: Bug 1559232: Add offset-position.
99 return nsCSSPropertyIDSet{
100 eCSSProperty_transform, eCSSProperty_translate,
101 eCSSProperty_rotate, eCSSProperty_scale,
102 eCSSProperty_offset_path, eCSSProperty_offset_distance,
103 eCSSProperty_offset_rotate, eCSSProperty_offset_anchor};
106 static constexpr nsCSSPropertyIDSet OpacityProperties() {
107 return nsCSSPropertyIDSet{eCSSProperty_opacity};
110 bool Intersects(const nsCSSPropertyIDSet& aOther) const {
111 for (size_t i = 0; i < mozilla::ArrayLength(mProperties); ++i) {
112 if (mProperties[i] & aOther.mProperties[i]) {
113 return true;
116 return false;
119 void Empty() { memset(mProperties, 0, sizeof(mProperties)); }
121 void AssertIsEmpty(const char* aText) const {
122 for (size_t i = 0; i < mozilla::ArrayLength(mProperties); ++i) {
123 NS_ASSERTION(mProperties[i] == 0, aText);
127 bool Equals(const nsCSSPropertyIDSet& aOther) const {
128 return mozilla::ArrayEqual(mProperties, aOther.mProperties);
131 bool IsEmpty() const {
132 for (size_t i = 0; i < mozilla::ArrayLength(mProperties); ++i) {
133 if (mProperties[i] != 0) {
134 return false;
137 return true;
140 bool IsSubsetOf(const nsCSSPropertyIDSet& aOther) const {
141 return this->Intersect(aOther).Equals(*this);
144 // Return a new nsCSSPropertyIDSet which is the inverse of this set.
145 nsCSSPropertyIDSet Inverse() const {
146 nsCSSPropertyIDSet result;
147 for (size_t i = 0; i < mozilla::ArrayLength(mProperties); ++i) {
148 result.mProperties[i] = ~mProperties[i];
150 return result;
153 // Returns a new nsCSSPropertyIDSet with all properties that are both in
154 // this set and |aOther|.
155 nsCSSPropertyIDSet Intersect(const nsCSSPropertyIDSet& aOther) const {
156 nsCSSPropertyIDSet result;
157 for (size_t i = 0; i < mozilla::ArrayLength(mProperties); ++i) {
158 result.mProperties[i] = mProperties[i] & aOther.mProperties[i];
160 return result;
163 // Return a new nsCSSPropertyIDSet with all properties that are in either
164 // this set or |aOther| but not both.
165 nsCSSPropertyIDSet Xor(const nsCSSPropertyIDSet& aOther) const {
166 nsCSSPropertyIDSet result;
167 for (size_t i = 0; i < mozilla::ArrayLength(mProperties); ++i) {
168 result.mProperties[i] = mProperties[i] ^ aOther.mProperties[i];
170 return result;
173 nsCSSPropertyIDSet& operator|=(const nsCSSPropertyIDSet& aOther) {
174 for (size_t i = 0; i < mozilla::ArrayLength(mProperties); ++i) {
175 mProperties[i] |= aOther.mProperties[i];
177 return *this;
180 private:
181 typedef unsigned long property_set_type;
183 public:
184 // number of bits in |property_set_type|.
185 static const size_t kBitsInChunk = sizeof(property_set_type) * CHAR_BIT;
186 // number of |property_set_type|s in the set
187 static const size_t kChunkCount =
188 (eCSSProperty_COUNT_no_shorthands + kBitsInChunk - 1) / kBitsInChunk;
191 * For fast enumeration of all the bits that are set, callers can
192 * check each chunk against zero (since in normal cases few bits are
193 * likely to be set).
195 bool HasPropertyInChunk(size_t aChunk) const {
196 return mProperties[aChunk] != 0;
198 bool HasPropertyAt(size_t aChunk, size_t aBit) const {
199 return (mProperties[aChunk] & (property_set_type(1) << aBit)) != 0;
201 static nsCSSPropertyID CSSPropertyAt(size_t aChunk, size_t aBit) {
202 return nsCSSPropertyID(aChunk * kBitsInChunk + aBit);
205 // Iterator for use in range-based for loops
206 class Iterator {
207 public:
208 Iterator(Iterator&& aOther)
209 : mPropertySet(aOther.mPropertySet),
210 mChunk(aOther.mChunk),
211 mBit(aOther.mBit) {}
213 static Iterator BeginIterator(const nsCSSPropertyIDSet& aPropertySet) {
214 Iterator result(aPropertySet);
216 // Search for the first property.
217 // Unsigned integer overflow is defined so the following is safe.
218 result.mBit = -1;
219 ++result;
221 return result;
224 static Iterator EndIterator(const nsCSSPropertyIDSet& aPropertySet) {
225 Iterator result(aPropertySet);
226 result.mChunk = kChunkCount;
227 result.mBit = 0;
228 return result;
231 bool operator!=(const Iterator& aOther) const {
232 return mChunk != aOther.mChunk || mBit != aOther.mBit;
235 Iterator& operator++() {
236 MOZ_ASSERT(mChunk < kChunkCount, "Should not iterate beyond end");
238 do {
239 mBit++;
240 } while (mBit < kBitsInChunk &&
241 !mPropertySet.HasPropertyAt(mChunk, mBit));
242 if (mBit != kBitsInChunk) {
243 return *this;
246 do {
247 mChunk++;
248 } while (mChunk < kChunkCount &&
249 !mPropertySet.HasPropertyInChunk(mChunk));
250 mBit = 0;
251 if (mChunk != kChunkCount) {
252 while (mBit < kBitsInChunk &&
253 !mPropertySet.HasPropertyAt(mChunk, mBit)) {
254 mBit++;
258 return *this;
261 nsCSSPropertyID operator*() {
262 MOZ_ASSERT(mChunk < kChunkCount, "Should not dereference beyond end");
263 return nsCSSPropertyIDSet::CSSPropertyAt(mChunk, mBit);
266 private:
267 explicit Iterator(const nsCSSPropertyIDSet& aPropertySet)
268 : mPropertySet(aPropertySet) {}
270 Iterator() = delete;
271 Iterator(const Iterator&) = delete;
272 Iterator& operator=(const Iterator&) = delete;
273 Iterator& operator=(const Iterator&&) = delete;
275 const nsCSSPropertyIDSet& mPropertySet;
276 size_t mChunk = 0;
277 size_t mBit = 0;
280 Iterator begin() const { return Iterator::BeginIterator(*this); }
281 Iterator end() const { return Iterator::EndIterator(*this); }
283 private:
284 property_set_type mProperties[kChunkCount];
287 // MOZ_DBG support
289 inline std::ostream& operator<<(std::ostream& aOut,
290 const nsCSSPropertyIDSet& aPropertySet) {
291 AutoTArray<nsCSSPropertyID, 16> properties;
292 for (nsCSSPropertyID property : aPropertySet) {
293 properties.AppendElement(property);
295 return aOut << properties;
298 #endif /* !defined(nsCSSPropertyIDSet_h__) */