| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_PRIORITY_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_PRIORITY_H_ |
| |
| #include "base/check_op.h" |
| #include "third_party/blink/renderer/core/core_export.h" |
| #include "third_party/blink/renderer/core/css/resolver/cascade_origin.h" |
| |
| namespace blink { |
| |
| // The origin and importance criteria are evaluated together [1], hence we |
| // encode both into a single integer which will do the right thing when compared |
| // to another such encoded integer. See CascadeOrigin for more information on |
| // how that works. |
| // |
| // [1] https://www.w3.org/TR/css-cascade-3/#cascade-origin |
| inline uint64_t EncodeOriginImportance(CascadeOrigin origin, bool important) { |
| uint8_t important_xor = (static_cast<uint8_t>(!important) - 1) & 0xF; |
| return static_cast<uint64_t>(origin) ^ important_xor; |
| } |
| |
| // Tree order bits are flipped for important declarations to reverse the |
| // priority [1]. |
| // |
| // [1] https://drafts.csswg.org/css-scoping/#shadow-cascading |
| inline uint64_t EncodeTreeOrder(uint16_t tree_order, bool important) { |
| uint16_t important_xor = static_cast<uint16_t>(!important) - 1; |
| return static_cast<uint64_t>(tree_order) ^ important_xor; |
| } |
| |
| // The CascadePriority class encapsulates a subset of the cascading criteria |
| // described by css-cascade [1], and provides a way to compare priorities |
| // quickly by encoding all the information in a single integer. |
| // |
| // It encompasses, from most significant to least significant: |
| // Origin/importance; tree order, which is a number representing the |
| // shadow-including tree order [2]; position, which contains the index (or |
| // indices) required to lookup a declaration in the underlying structure (e.g. a |
| // MatchResult); and finally generation, which is a monotonically increasing |
| // number generated by StyleCascade for each call to StyleCascade::Apply. |
| // |
| // [1] https://drafts.csswg.org/css-cascade/#cascading |
| // [2] https://drafts.csswg.org/css-scoping/#shadow-cascading |
| class CORE_EXPORT CascadePriority { |
| public: |
| // The declaration is important if this bit is set on the encoded priority. |
| static constexpr uint64_t kImportantBit = 55; |
| static constexpr uint64_t kOriginImportanceOffset = 52; |
| static constexpr uint64_t kTreeOrderOffset = 36; |
| |
| CascadePriority() : bits_(0) {} |
| CascadePriority(CascadeOrigin origin) |
| : CascadePriority(origin, false, 0, 0) {} |
| CascadePriority(CascadeOrigin origin, bool important) |
| : CascadePriority(origin, important, 0, 0) {} |
| CascadePriority(CascadeOrigin origin, bool important, uint16_t tree_order) |
| : CascadePriority(origin, important, tree_order, 0) {} |
| // For an explanation of 'tree_order', see css-scoping: |
| // https://drafts.csswg.org/css-scoping/#shadow-cascading |
| CascadePriority(CascadeOrigin origin, |
| bool important, |
| uint16_t tree_order, |
| uint32_t position) |
| : bits_(static_cast<uint64_t>(position) << 4 | |
| EncodeTreeOrder(tree_order, important) << kTreeOrderOffset | |
| EncodeOriginImportance(origin, important) |
| << kOriginImportanceOffset) {} |
| // See StyleCascade.generation_. |
| CascadePriority(CascadePriority o, uint8_t generation) |
| : bits_((o.bits_ & ~static_cast<uint8_t>(0xF)) | generation) { |
| DCHECK_LE(generation, 0xF); |
| } |
| |
| bool IsImportant() const { return (bits_ >> kImportantBit) & 1; } |
| CascadeOrigin GetOrigin() const { |
| uint64_t important_xor = (((~bits_ >> kImportantBit) & 1) - 1) & 0xF; |
| return static_cast<CascadeOrigin>((bits_ >> kOriginImportanceOffset) ^ |
| important_xor); |
| } |
| bool HasOrigin() const { return GetOrigin() != CascadeOrigin::kNone; } |
| uint32_t GetPosition() const { return (bits_ >> 4) & 0xFFFFFFFF; } |
| uint8_t GetGeneration() const { return bits_ & 0xF; } |
| |
| bool operator>=(const CascadePriority& o) const { return bits_ >= o.bits_; } |
| bool operator<(const CascadePriority& o) const { return bits_ < o.bits_; } |
| bool operator==(const CascadePriority& o) const { return bits_ == o.bits_; } |
| bool operator!=(const CascadePriority& o) const { return bits_ != o.bits_; } |
| |
| private: |
| friend class StyleCascade; |
| friend class StyleCascadeTest; |
| |
| CascadePriority(uint64_t bits) : bits_(bits) {} |
| |
| // Bit 0-3 : generation |
| // Bit 4-35: position |
| // Bit 36-51: tree_order (encoded) |
| // Bit 52-59: origin/importance (encoded) |
| uint64_t bits_; |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_PRIORITY_H_ |