blob: 886f1a916cb618ce8f19dfaa51a82a0d8fbb661c [file] [log] [blame]
// Copyright 2017 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_CSSOM_CSS_NUMERIC_VALUE_TYPE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_NUMERIC_VALUE_TYPE_H_
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include <array>
namespace blink {
// Represents the type of a CSSNumericValue, which is a map of base types to
// integers, and an associated percent hint.
// https://drafts.css-houdini.org/css-typed-om/#numeric-typing
class CORE_EXPORT CSSNumericValueType {
public:
enum class BaseType : unsigned {
kLength,
kAngle,
kTime,
kFrequency,
kResolution,
kFlex,
kPercent,
kNumBaseTypes
};
static constexpr unsigned kNumBaseTypes =
static_cast<unsigned>(BaseType::kNumBaseTypes);
static AtomicString BaseTypeToString(BaseType);
explicit CSSNumericValueType(
CSSPrimitiveValue::UnitType = CSSPrimitiveValue::UnitType::kNumber);
CSSNumericValueType(int exponent, CSSPrimitiveValue::UnitType);
static CSSNumericValueType NegateExponents(CSSNumericValueType);
static CSSNumericValueType Add(CSSNumericValueType,
CSSNumericValueType,
bool& error);
static CSSNumericValueType Multiply(CSSNumericValueType,
CSSNumericValueType,
bool& error);
int Exponent(BaseType type) const {
DCHECK_LT(type, BaseType::kNumBaseTypes);
return exponents_[static_cast<unsigned>(type)];
}
void SetExponent(BaseType type, int new_value) {
DCHECK_LT(type, BaseType::kNumBaseTypes);
int& old_value = exponents_[static_cast<unsigned>(type)];
if (old_value == 0 && new_value != 0)
num_non_zero_entries_++;
else if (old_value != 0 && new_value == 0)
num_non_zero_entries_--;
old_value = new_value;
}
bool HasPercentHint() const { return has_percent_hint_; }
BaseType PercentHint() const { return percent_hint_; }
void ApplyPercentHint(BaseType hint);
bool MatchesBaseType(BaseType base_type) const {
DCHECK_NE(base_type, BaseType::kPercent);
return IsOnlyNonZeroEntry(base_type, 1) && !HasPercentHint();
}
bool MatchesPercentage() const {
return IsOnlyNonZeroEntry(BaseType::kPercent, 1);
}
bool MatchesBaseTypePercentage(BaseType base_type) const {
DCHECK_NE(base_type, BaseType::kPercent);
return IsOnlyNonZeroEntry(base_type, 1) ||
IsOnlyNonZeroEntry(BaseType::kPercent, 1);
}
bool MatchesNumber() const {
return !HasNonZeroEntries() && !HasPercentHint();
}
bool MatchesNumberPercentage() const {
return !HasNonZeroEntries() || IsOnlyNonZeroEntry(BaseType::kPercent, 1);
}
private:
bool HasNonZeroEntries() const { return num_non_zero_entries_ > 0; }
bool IsOnlyNonZeroEntry(BaseType base_type, int value) const {
DCHECK_NE(value, 0);
return num_non_zero_entries_ == 1 && Exponent(base_type) == value;
}
std::array<int, kNumBaseTypes> exponents_{}; // zero-initialize
BaseType percent_hint_ = BaseType::kPercent;
bool has_percent_hint_ = false;
unsigned num_non_zero_entries_ = 0;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSSOM_CSS_NUMERIC_VALUE_TYPE_H_