1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_FILTER_H_ 6 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_FILTER_H_ 7 8 #include "third_party/blink/renderer/core/core_export.h" 9 #include "third_party/blink/renderer/core/css/properties/css_property.h" 10 11 namespace blink { 12 13 // Reject properties with the given flags set or unset. 14 // 15 // For example, the following applies only inherited properties that don't apply 16 // to ::first-letter: 17 // 18 // CascadeFilter filter; 19 // filter = filter.Add(CSSProperty::kInherited, false); 20 // filter = filter.Add(CSSProperty::kValidForFirstLetter, true); 21 // filter.Reject(GetCSSPropertyColor()); // -> false 22 // filter.Reject(GetCSSPropertyDirection()); // -> true 23 // filter.Reject(GetCSSPropertyTop()); // -> true 24 // 25 class CORE_EXPORT CascadeFilter { 26 public: 27 // Empty filter. Rejects nothing. 28 CascadeFilter() = default; 29 30 // Creates a filter with a single rule. 31 // 32 // This is equivalent to: 33 // 34 // CascadeFilter filter; 35 // filter.Add(flag, v); 36 // CascadeFilter(CSSProperty::Flag flag,bool v)37 CascadeFilter(CSSProperty::Flag flag, bool v) 38 : mask_(flag), flags_(v ? flag : 0) {} 39 40 bool operator==(const CascadeFilter& o) const { 41 return mask_ == o.mask_ && flags_ == o.flags_; 42 } 43 bool operator!=(const CascadeFilter& o) const { 44 return mask_ != o.mask_ || flags_ != o.flags_; 45 } 46 47 // Add a given rule to the filter. 48 // 49 // A flag can be rejected when it's either set or unset. For example 50 // 51 // CascadeFilter f1(CSSProperty::kInherited, true); // Rejects inherited 52 // CascadeFilter f2(CSSProperty::kInherited, false); // Rejects non-inherited 53 // 54 // Note that it's not possible to reject both set and unset flags in the same 55 // filter. However, if you wish to reject all properties, you can do so by 56 // using the CSSProperty::kProperty flag. 57 // 58 // Add() will have no effect if there already is a rule for the given flag: 59 // 60 // CascadeFilter filter; 61 // CascadeFilter f1 = filter.Add(CSSProperty::kInherited, true); 62 // CascadeFilter f2 = f1.Add(CSSProperty::kInherited, false); 63 // bool equal = f1 == f2; // true. Second call to Add had to effect. 64 // 65 // If you want to overwrite a previous rule, use Set(). Add(CSSProperty::Flag flag,bool v)66 CascadeFilter Add(CSSProperty::Flag flag, bool v) const { 67 const CSSProperty::Flags mask = mask_ | flag; 68 const CSSProperty::Flags flags = 69 v ? (flags_ | (flag & ~mask_)) : (flags_ & ~(flag & ~mask_)); 70 return CascadeFilter(mask, flags); 71 } 72 73 // Like Add, except overwrites a previous rule for the same flag. Set(CSSProperty::Flag flag,bool v)74 CascadeFilter Set(CSSProperty::Flag flag, bool v) const { 75 const CSSProperty::Flags mask = mask_ | flag; 76 const CSSProperty::Flags flags = v ? (flags_ | flag) : (flags_ & ~flag); 77 return CascadeFilter(mask, flags); 78 } 79 Rejects(const CSSProperty & property)80 bool Rejects(const CSSProperty& property) const { 81 return ~(property.GetFlags() ^ flags_) & mask_; 82 } 83 Rejects(CSSProperty::Flag flag,bool v)84 bool Rejects(CSSProperty::Flag flag, bool v) const { 85 return ~((v ? flag : 0) ^ flags_) & (mask_ & flag); 86 } 87 88 private: CascadeFilter(CSSProperty::Flags mask,CSSProperty::Flags flags)89 CascadeFilter(CSSProperty::Flags mask, CSSProperty::Flags flags) 90 : mask_(mask), flags_(flags) {} 91 // Specifies which bits are significant in flags_. In other words, mask_ 92 // contains a '1' at the corresponding position for each flag seen by 93 // Add(). 94 CSSProperty::Flags mask_ = 0; 95 // Contains the flags to exclude. Only bits set in mask_ matter. 96 CSSProperty::Flags flags_ = 0; 97 }; 98 99 } // namespace blink 100 101 #endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_FILTER_H_ 102