| /* |
| * Copyright (C) 2019 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer. |
| * 2. Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials |
| * provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
| * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
| * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
| * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "CSSUnitValue.h" |
| |
| #if ENABLE(CSS_TYPED_OM) |
| |
| #include "CSSParserToken.h" |
| #include "CSSPrimitiveValue.h" |
| #include <wtf/IsoMallocInlines.h> |
| |
| namespace WebCore { |
| |
| WTF_MAKE_ISO_ALLOCATED_IMPL(CSSUnitValue); |
| |
| CSSUnitType CSSUnitValue::parseUnit(const String& unit) |
| { |
| if (unit == "number"_s) |
| return CSSUnitType::CSS_NUMBER; |
| if (unit == "percent"_s) |
| return CSSUnitType::CSS_PERCENTAGE; |
| |
| // FIXME: Remove these when LineHeightUnitsEnabled is changed back to true or removed |
| // https://bugs.webkit.org/show_bug.cgi?id=211351 |
| if (unit == "lh"_s) |
| return CSSUnitType::CSS_LHS; |
| if (unit == "rlh"_s) |
| return CSSUnitType::CSS_RLHS; |
| |
| return CSSParserToken::stringToUnitType(unit); |
| } |
| |
| ASCIILiteral CSSUnitValue::unit() const |
| { |
| switch (m_unit) { |
| case CSSUnitType::CSS_NUMBER: |
| return "number"_s; |
| case CSSUnitType::CSS_PERCENTAGE: |
| return "percent"_s; |
| default: |
| break; |
| } |
| return unitSerialization(); |
| } |
| |
| ASCIILiteral CSSUnitValue::unitSerialization() const |
| { |
| return CSSPrimitiveValue::unitTypeString(m_unit); |
| } |
| |
| void CSSUnitValue::serialize(StringBuilder& builder, OptionSet<SerializationArguments>) const |
| { |
| builder.append(FormattedCSSNumber::create(m_value)); |
| builder.append(unitSerialization()); |
| } |
| |
| ExceptionOr<Ref<CSSUnitValue>> CSSUnitValue::create(double value, const String& unit) |
| { |
| auto parsedUnit = parseUnit(unit); |
| if (parsedUnit == CSSUnitType::CSS_UNKNOWN) |
| return Exception { TypeError }; |
| auto type = CSSNumericType::create(parsedUnit); |
| if (!type) |
| return Exception { TypeError }; |
| auto unitValue = adoptRef(*new CSSUnitValue(value, parsedUnit)); |
| unitValue->m_type = WTFMove(*type); |
| return unitValue; |
| } |
| |
| CSSUnitValue::CSSUnitValue(double value, CSSUnitType unit) |
| : CSSNumericValue(CSSNumericType::create(unit).value_or(CSSNumericType())) |
| , m_value(value) |
| , m_unit(unit) |
| { |
| } |
| |
| static double conversionToCanonicalUnitsScaleFactor(CSSUnitType unit) |
| { |
| constexpr double pixelsPerInch = 96; |
| constexpr double pixelsPerCentimeter = pixelsPerInch / 2.54; |
| constexpr double pointsPerInch = 72; |
| constexpr double picasPerInch = 6; |
| |
| switch (unit) { |
| case CSSUnitType::CSS_MS: |
| return 0.001; |
| case CSSUnitType::CSS_CM: |
| return pixelsPerCentimeter; |
| case CSSUnitType::CSS_DPCM: |
| return 1.0 / pixelsPerCentimeter; |
| case CSSUnitType::CSS_MM: |
| return pixelsPerCentimeter / 10; |
| case CSSUnitType::CSS_Q: |
| return pixelsPerCentimeter / 40; |
| case CSSUnitType::CSS_IN: |
| return pixelsPerInch; |
| case CSSUnitType::CSS_DPI: |
| return 1.0 / pixelsPerInch; |
| case CSSUnitType::CSS_PT: |
| return pixelsPerInch / pointsPerInch; |
| case CSSUnitType::CSS_PC: |
| return pixelsPerInch / picasPerInch; |
| case CSSUnitType::CSS_RAD: |
| return 180 / piDouble; |
| case CSSUnitType::CSS_GRAD: |
| return 0.9; |
| case CSSUnitType::CSS_TURN: |
| return 360; |
| case CSSUnitType::CSS_KHZ: |
| return 1000; |
| default: |
| return 1.0; |
| } |
| } |
| |
| RefPtr<CSSUnitValue> CSSUnitValue::convertTo(CSSUnitType unit) const |
| { |
| // https://drafts.css-houdini.org/css-typed-om/#convert-a-cssunitvalue |
| if (unitCategory(unitEnum()) != unitCategory(unit)) |
| return nullptr; |
| |
| return create(m_value * conversionToCanonicalUnitsScaleFactor(unitEnum()) / conversionToCanonicalUnitsScaleFactor(unit), unit); |
| } |
| |
| auto CSSUnitValue::toSumValue() const -> std::optional<SumValue> |
| { |
| // https://drafts.css-houdini.org/css-typed-om/#create-a-sum-value |
| auto canonicalUnit = [] (CSSUnitType unit) { |
| // FIXME: We probably want to change the definition of canonicalUnitTypeForCategory so this lambda isn't necessary. |
| auto category = unitCategory(unit); |
| switch (category) { |
| case CSSUnitCategory::Percent: |
| return CSSUnitType::CSS_PERCENTAGE; |
| case CSSUnitCategory::Other: |
| if (unit == CSSUnitType::CSS_FR) |
| return CSSUnitType::CSS_FR; |
| break; |
| default: |
| break; |
| } |
| return canonicalUnitTypeForCategory(category); |
| } (m_unit); |
| auto convertedValue = m_value * conversionToCanonicalUnitsScaleFactor(unitEnum()) / conversionToCanonicalUnitsScaleFactor(canonicalUnit); |
| |
| if (m_unit == CSSUnitType::CSS_NUMBER) |
| return { { { convertedValue, { } } } }; |
| return { { { convertedValue, { { canonicalUnit, 1 } } } } }; |
| } |
| |
| bool CSSUnitValue::equals(const CSSNumericValue& other) const |
| { |
| // https://drafts.css-houdini.org/css-typed-om/#equal-numeric-value |
| auto* otherUnitValue = dynamicDowncast<CSSUnitValue>(other); |
| if (!otherUnitValue) |
| return false; |
| return m_value == otherUnitValue->m_value && m_unit == otherUnitValue->m_unit; |
| } |
| |
| } // namespace WebCore |
| |
| #endif |