Commit 0800969a authored by Darren Shen's avatar Darren Shen Committed by Commit Bot

[css-typed-om] Simplify CSSUnitValue conversion.

Currently, when we convert a CSSUnitValue to a different unit, we
essentially consult a NxN table to figure out the scale factor, where
N is the number of units.

An easier way is to first convert to the canonical unit, then convert
from the canonical unit to the target unit. This only requires a lookup
table of size N instead of NxN, greatly simplifying the code.

Bug: 776173
Change-Id: Icb28386938f9cb7de4d917c72426154b8f45d6e6
Reviewed-on: https://chromium-review.googlesource.com/798930Reviewed-by: default avatarnainar <nainar@chromium.org>
Commit-Queue: Darren Shen <shend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#520848}
parent e1b7ac80
...@@ -24,8 +24,11 @@ test(() => { ...@@ -24,8 +24,11 @@ test(() => {
}, 'Converting a CSSUnitValue to an incompatible unit throws TypeError'); }, 'Converting a CSSUnitValue to an incompatible unit throws TypeError');
test(() => { test(() => {
assert_style_value_equals(CSS.number(1).to('number'), CSS.number(1)); for (const unit of gValidUnits) {
assert_style_value_equals(CSS.px(1).to('px'), CSS.px(1)); // FIXME(778495): Remove this check onec all the units are supported.
if (CSS[unit])
assert_style_value_equals(CSS[unit](1).to(unit), CSS[unit](1));
}
}, 'Converting a CSSUnitValue to its own unit returns itself'); }, 'Converting a CSSUnitValue to its own unit returns itself');
// TODO(776173): cssUnitValue_toMethod.html has more comprehensive tests of converting // TODO(776173): cssUnitValue_toMethod.html has more comprehensive tests of converting
......
...@@ -22,6 +22,14 @@ CSSPrimitiveValue::UnitType ToCanonicalUnit(CSSPrimitiveValue::UnitType unit) { ...@@ -22,6 +22,14 @@ CSSPrimitiveValue::UnitType ToCanonicalUnit(CSSPrimitiveValue::UnitType unit) {
CSSPrimitiveValue::UnitTypeToUnitCategory(unit)); CSSPrimitiveValue::UnitTypeToUnitCategory(unit));
} }
CSSPrimitiveValue::UnitType ToCanonicalUnitIfPossible(
CSSPrimitiveValue::UnitType unit) {
const auto canonical_unit = ToCanonicalUnit(unit);
if (canonical_unit == CSSPrimitiveValue::UnitType::kUnknown)
return unit;
return canonical_unit;
}
} // namespace } // namespace
CSSUnitValue* CSSUnitValue::Create(double value, CSSUnitValue* CSSUnitValue::Create(double value,
...@@ -97,33 +105,31 @@ const CSSValue* CSSUnitValue::ToCSSValue(SecureContextMode) const { ...@@ -97,33 +105,31 @@ const CSSValue* CSSUnitValue::ToCSSValue(SecureContextMode) const {
return CSSPrimitiveValue::Create(value_, unit_); return CSSPrimitiveValue::Create(value_, unit_);
} }
CSSUnitValue* CSSUnitValue::ConvertTo(CSSPrimitiveValue::UnitType unit) const { CSSUnitValue* CSSUnitValue::ConvertTo(
if (unit_ == unit) CSSPrimitiveValue::UnitType target_unit) const {
if (unit_ == target_unit)
return Create(value_, unit_); return Create(value_, unit_);
// TODO(meade): Implement other types: time, frequency and resolution. // Instead of defining the scale factors for every unit to every other unit,
if (CSSPrimitiveValue::IsLength(unit_) && CSSPrimitiveValue::IsLength(unit)) { // we simply convert to the canonical unit and back since we already have
// Only fixed lengths can be converted. // the scale factors for canonical units.
if (CSSPrimitiveValue::IsRelativeUnit(unit_) || const auto canonical_unit = ToCanonicalUnit(unit_);
CSSPrimitiveValue::IsRelativeUnit(unit)) if (canonical_unit != ToCanonicalUnit(target_unit) ||
return nullptr; canonical_unit == CSSPrimitiveValue::UnitType::kUnknown)
return Create(ConvertFixedLength(unit), unit); return nullptr;
}
if (CSSPrimitiveValue::IsAngle(unit_) && CSSPrimitiveValue::IsAngle(unit))
return Create(ConvertAngle(unit), unit);
return nullptr; const double scale_factor =
CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor(unit_) /
CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor(target_unit);
return CSSUnitValue::Create(value_ * scale_factor, target_unit);
} }
WTF::Optional<CSSNumericSumValue> CSSUnitValue::SumValue() const { WTF::Optional<CSSNumericSumValue> CSSUnitValue::SumValue() const {
const auto canonical_unit = ToCanonicalUnit(unit_);
if (canonical_unit == CSSPrimitiveValue::UnitType::kUnknown)
return WTF::nullopt;
CSSNumericSumValue sum; CSSNumericSumValue sum;
CSSNumericSumValue::UnitMap unit_map; CSSNumericSumValue::UnitMap unit_map;
if (unit_ != CSSPrimitiveValue::UnitType::kNumber) if (unit_ != CSSPrimitiveValue::UnitType::kNumber)
unit_map.insert(canonical_unit, 1); unit_map.insert(ToCanonicalUnitIfPossible(unit_), 1);
sum.terms.emplace_back( sum.terms.emplace_back(
value_ * CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor(unit_), value_ * CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor(unit_),
...@@ -131,201 +137,6 @@ WTF::Optional<CSSNumericSumValue> CSSUnitValue::SumValue() const { ...@@ -131,201 +137,6 @@ WTF::Optional<CSSNumericSumValue> CSSUnitValue::SumValue() const {
return sum; return sum;
} }
double CSSUnitValue::ConvertFixedLength(
CSSPrimitiveValue::UnitType unit) const {
switch (unit_) {
case CSSPrimitiveValue::UnitType::kPixels:
switch (unit) {
case CSSPrimitiveValue::UnitType::kCentimeters:
return value_ / kCssPixelsPerCentimeter;
case CSSPrimitiveValue::UnitType::kMillimeters:
return value_ / kCssPixelsPerMillimeter;
case CSSPrimitiveValue::UnitType::kQuarterMillimeters:
return value_ / kCssPixelsPerQuarterMillimeter;
case CSSPrimitiveValue::UnitType::kInches:
return value_ / kCssPixelsPerInch;
case CSSPrimitiveValue::UnitType::kPoints:
return value_ / kCssPixelsPerPoint;
case CSSPrimitiveValue::UnitType::kPicas:
return value_ / kCssPixelsPerPica;
default:
NOTREACHED();
return 0;
}
case CSSPrimitiveValue::UnitType::kCentimeters:
switch (unit) {
case CSSPrimitiveValue::UnitType::kPixels:
return value_ * kCssPixelsPerCentimeter;
case CSSPrimitiveValue::UnitType::kMillimeters:
return value_ * kMillimetersPerCentimeter;
case CSSPrimitiveValue::UnitType::kQuarterMillimeters:
return value_ * kQuarterMillimetersPerCentimeter;
case CSSPrimitiveValue::UnitType::kInches:
return value_ / kCentimetersPerInch;
case CSSPrimitiveValue::UnitType::kPoints:
return value_ * (kPointsPerInch / kCentimetersPerInch);
case CSSPrimitiveValue::UnitType::kPicas:
return value_ * (kPicasPerInch / kCentimetersPerInch);
default:
NOTREACHED();
return 0;
}
case CSSPrimitiveValue::UnitType::kMillimeters:
switch (unit) {
case CSSPrimitiveValue::UnitType::kPixels:
return value_ * kCssPixelsPerMillimeter;
case CSSPrimitiveValue::UnitType::kCentimeters:
return value_ / kMillimetersPerCentimeter;
case CSSPrimitiveValue::UnitType::kQuarterMillimeters:
return value_ *
(kQuarterMillimetersPerCentimeter / kMillimetersPerCentimeter);
case CSSPrimitiveValue::UnitType::kInches:
return value_ / (kMillimetersPerCentimeter * kCentimetersPerInch);
case CSSPrimitiveValue::UnitType::kPoints:
return value_ * (kPointsPerInch / kMillimetersPerInch);
case CSSPrimitiveValue::UnitType::kPicas:
return value_ * (kPicasPerInch / kMillimetersPerInch);
default:
NOTREACHED();
return 0;
}
case CSSPrimitiveValue::UnitType::kQuarterMillimeters:
switch (unit) {
case CSSPrimitiveValue::UnitType::kPixels:
return value_ * kCssPixelsPerQuarterMillimeter;
case CSSPrimitiveValue::UnitType::kCentimeters:
return value_ / kQuarterMillimetersPerCentimeter;
case CSSPrimitiveValue::UnitType::kMillimeters:
return value_ /
(kQuarterMillimetersPerCentimeter / kMillimetersPerCentimeter);
case CSSPrimitiveValue::UnitType::kInches:
return value_ /
(kQuarterMillimetersPerCentimeter * kCentimetersPerInch);
case CSSPrimitiveValue::UnitType::kPoints:
return value_ * (kPointsPerInch / kQuarterMillimetersPerInch);
case CSSPrimitiveValue::UnitType::kPicas:
return value_ * (kPicasPerInch / kQuarterMillimetersPerInch);
default:
NOTREACHED();
return 0;
}
case CSSPrimitiveValue::UnitType::kInches:
switch (unit) {
case CSSPrimitiveValue::UnitType::kPixels:
return value_ * kCssPixelsPerInch;
case CSSPrimitiveValue::UnitType::kMillimeters:
return value_ * kCentimetersPerInch * kMillimetersPerCentimeter;
case CSSPrimitiveValue::UnitType::kQuarterMillimeters:
return value_ * kCentimetersPerInch *
kQuarterMillimetersPerCentimeter;
case CSSPrimitiveValue::UnitType::kCentimeters:
return value_ * kCentimetersPerInch;
case CSSPrimitiveValue::UnitType::kPoints:
return value_ * kPointsPerInch;
case CSSPrimitiveValue::UnitType::kPicas:
return value_ * kPicasPerInch;
default:
NOTREACHED();
return 0;
}
case CSSPrimitiveValue::UnitType::kPoints:
switch (unit) {
case CSSPrimitiveValue::UnitType::kPixels:
return value_ * kCssPixelsPerPoint;
case CSSPrimitiveValue::UnitType::kMillimeters:
return value_ * (kMillimetersPerInch / kPointsPerInch);
case CSSPrimitiveValue::UnitType::kQuarterMillimeters:
return value_ * (kQuarterMillimetersPerInch / kPointsPerInch);
case CSSPrimitiveValue::UnitType::kCentimeters:
return value_ * (kCentimetersPerInch / kPointsPerInch);
case CSSPrimitiveValue::UnitType::kInches:
return value_ / kPointsPerInch;
case CSSPrimitiveValue::UnitType::kPicas:
return value_ * (kPicasPerInch / kPointsPerInch);
default:
NOTREACHED();
return 0;
}
case CSSPrimitiveValue::UnitType::kPicas:
switch (unit) {
case CSSPrimitiveValue::UnitType::kPixels:
return value_ * kCssPixelsPerPica;
case CSSPrimitiveValue::UnitType::kMillimeters:
return value_ * (kMillimetersPerInch / kPicasPerInch);
case CSSPrimitiveValue::UnitType::kQuarterMillimeters:
return value_ * (kQuarterMillimetersPerInch / kPicasPerInch);
case CSSPrimitiveValue::UnitType::kCentimeters:
return value_ * (kCentimetersPerInch / kPicasPerInch);
case CSSPrimitiveValue::UnitType::kInches:
return value_ / kPicasPerInch;
case CSSPrimitiveValue::UnitType::kPoints:
return value_ * (kPointsPerInch / kPicasPerInch);
default:
NOTREACHED();
return 0;
}
default:
NOTREACHED();
return 0;
}
}
double CSSUnitValue::ConvertAngle(CSSPrimitiveValue::UnitType unit) const {
switch (unit_) {
case CSSPrimitiveValue::UnitType::kDegrees:
switch (unit) {
case CSSPrimitiveValue::UnitType::kRadians:
return deg2rad(value_);
case CSSPrimitiveValue::UnitType::kGradians:
return deg2grad(value_);
case CSSPrimitiveValue::UnitType::kTurns:
return deg2turn(value_);
default:
NOTREACHED();
return 0;
}
case CSSPrimitiveValue::UnitType::kRadians:
switch (unit) {
case CSSPrimitiveValue::UnitType::kDegrees:
return rad2deg(value_);
case CSSPrimitiveValue::UnitType::kGradians:
return rad2grad(value_);
case CSSPrimitiveValue::UnitType::kTurns:
return rad2turn(value_);
default:
NOTREACHED();
return 0;
}
case CSSPrimitiveValue::UnitType::kGradians:
switch (unit) {
case CSSPrimitiveValue::UnitType::kDegrees:
return grad2deg(value_);
case CSSPrimitiveValue::UnitType::kRadians:
return grad2rad(value_);
case CSSPrimitiveValue::UnitType::kTurns:
return grad2turn(value_);
default:
NOTREACHED();
return 0;
}
case CSSPrimitiveValue::UnitType::kTurns:
switch (unit) {
case CSSPrimitiveValue::UnitType::kDegrees:
return turn2deg(value_);
case CSSPrimitiveValue::UnitType::kRadians:
return turn2rad(value_);
case CSSPrimitiveValue::UnitType::kGradians:
return turn2grad(value_);
default:
NOTREACHED();
return 0;
}
default:
NOTREACHED();
return 0;
}
}
bool CSSUnitValue::Equals(const CSSNumericValue& other) const { bool CSSUnitValue::Equals(const CSSNumericValue& other) const {
if (!other.IsUnitValue()) if (!other.IsUnitValue())
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment