blob: f41117d4fc52e73a9d9099482c9b446365dfd450 [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.
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value_type.h"
#include <algorithm>
namespace blink {
namespace {
CSSNumericValueType::BaseType UnitTypeToBaseType(
CSSPrimitiveValue::UnitType unit) {
using UnitType = CSSPrimitiveValue::UnitType;
using BaseType = CSSNumericValueType::BaseType;
DCHECK_NE(unit, UnitType::kNumber);
switch (unit) {
case UnitType::kEms:
case UnitType::kExs:
case UnitType::kPixels:
case UnitType::kCentimeters:
case UnitType::kMillimeters:
case UnitType::kQuarterMillimeters:
case UnitType::kInches:
case UnitType::kPoints:
case UnitType::kPicas:
case UnitType::kUserUnits:
case UnitType::kViewportWidth:
case UnitType::kViewportHeight:
case UnitType::kViewportMin:
case UnitType::kViewportMax:
case UnitType::kRems:
case UnitType::kChs:
return BaseType::kLength;
case UnitType::kMilliseconds:
case UnitType::kSeconds:
return BaseType::kTime;
case UnitType::kDegrees:
case UnitType::kRadians:
case UnitType::kGradians:
case UnitType::kTurns:
return BaseType::kAngle;
case UnitType::kHertz:
case UnitType::kKilohertz:
return BaseType::kFrequency;
case UnitType::kDotsPerPixel:
case UnitType::kDotsPerInch:
case UnitType::kDotsPerCentimeter:
return BaseType::kResolution;
case UnitType::kFraction:
return BaseType::kFlex;
case UnitType::kPercentage:
return BaseType::kPercent;
default:
NOTREACHED();
return BaseType::kLength;
}
}
} // namespace
AtomicString CSSNumericValueType::BaseTypeToString(BaseType base_type) {
switch (base_type) {
case BaseType::kLength:
return "length";
case BaseType::kAngle:
return "angle";
case BaseType::kTime:
return "time";
case BaseType::kFrequency:
return "frequency";
case BaseType::kResolution:
return "resolution";
case BaseType::kFlex:
return "flex";
case BaseType::kPercent:
return "percent";
default:
break;
}
NOTREACHED();
return "";
}
CSSNumericValueType::CSSNumericValueType(CSSPrimitiveValue::UnitType unit) {
if (unit != CSSPrimitiveValue::UnitType::kNumber)
SetExponent(UnitTypeToBaseType(unit), 1);
}
CSSNumericValueType::CSSNumericValueType(int exponent,
CSSPrimitiveValue::UnitType unit) {
if (unit != CSSPrimitiveValue::UnitType::kNumber)
SetExponent(UnitTypeToBaseType(unit), exponent);
}
CSSNumericValueType CSSNumericValueType::NegateExponents(
CSSNumericValueType type) {
std::for_each(type.exponents_.begin(), type.exponents_.end(),
[](int& v) { v *= -1; });
return type;
}
CSSNumericValueType CSSNumericValueType::Add(CSSNumericValueType type1,
CSSNumericValueType type2,
bool& error) {
if (type1.HasPercentHint() && type2.HasPercentHint() &&
type1.PercentHint() != type2.PercentHint()) {
error = true;
return type1;
}
if (type1.HasPercentHint())
type2.ApplyPercentHint(type1.PercentHint());
else if (type2.HasPercentHint())
type1.ApplyPercentHint(type2.PercentHint());
DCHECK_EQ(type1.PercentHint(), type2.PercentHint());
// Match up base types. Try to use the percent hint to match up any
// differences.
for (unsigned i = 0; i < kNumBaseTypes; ++i) {
const BaseType base_type = static_cast<BaseType>(i);
if (type1.exponents_[i] != type2.exponents_[i]) {
if (base_type != BaseType::kPercent) {
type1.ApplyPercentHint(base_type);
type2.ApplyPercentHint(base_type);
}
if (type1.exponents_[i] != type2.exponents_[i]) {
error = true;
return type1;
}
}
}
error = false;
return type1;
}
CSSNumericValueType CSSNumericValueType::Multiply(CSSNumericValueType type1,
CSSNumericValueType type2,
bool& error) {
if (type1.HasPercentHint() && type2.HasPercentHint() &&
type1.PercentHint() != type2.PercentHint()) {
error = true;
return type1;
}
if (type1.HasPercentHint())
type2.ApplyPercentHint(type1.PercentHint());
else if (type2.HasPercentHint())
type1.ApplyPercentHint(type2.PercentHint());
for (unsigned i = 0; i < kNumBaseTypes; ++i) {
const auto base_type = static_cast<BaseType>(i);
type1.SetExponent(base_type,
type1.Exponent(base_type) + type2.Exponent(base_type));
}
error = false;
return type1;
}
void CSSNumericValueType::ApplyPercentHint(BaseType hint) {
DCHECK_NE(hint, BaseType::kPercent);
SetExponent(hint, Exponent(hint) + Exponent(BaseType::kPercent));
SetExponent(BaseType::kPercent, 0);
percent_hint_ = hint;
has_percent_hint_ = true;
}
} // namespace blink