blob: afc3253510bba71e6675a913bb6958bd76406cb8 [file] [log] [blame]
// 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_