/* * (C) 1999-2003 Lars Knoll (knoll@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012 Apple Inc. All rights * reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include #include "build/build_config.h" #include "third_party/blink/renderer/core/css/css_markup.h" #include "third_party/blink/renderer/core/css/css_math_expression_node.h" #include "third_party/blink/renderer/core/css/css_math_function_value.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "third_party/blink/renderer/core/css/css_resolution_units.h" #include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h" #include "third_party/blink/renderer/core/css/css_value_clamping_utils.h" #include "third_party/blink/renderer/core/css/css_value_pool.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/size_assertions.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" namespace blink { namespace { // Max/min values for CSS, needs to slightly smaller/larger than the true // max/min values to allow for rounding without overflowing. // Subtract two (rather than one) to allow for values to be converted to float // and back without exceeding the LayoutUnit::Max. const int kMaxValueForCssLength = INT_MAX / kFixedPointDenominator - 2; const int kMinValueForCssLength = INT_MIN / kFixedPointDenominator + 2; } // namespace struct SameSizeAsCSSPrimitiveValue : CSSValue { }; ASSERT_SIZE(CSSPrimitiveValue, SameSizeAsCSSPrimitiveValue); float CSSPrimitiveValue::ClampToCSSLengthRange(double value) { // TODO(crbug.com/1133390): clampTo function could occur the DECHECK failure // for NaN value. Therefore, infinity and NaN values should not be clamped // here. if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) { value = CSSValueClampingUtils::ClampLength(value); } return clampTo(value, kMinValueForCssLength, kMaxValueForCssLength); } CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::UnitTypeToUnitCategory( UnitType type) { switch (type) { case UnitType::kNumber: return CSSPrimitiveValue::kUNumber; case UnitType::kPercentage: return CSSPrimitiveValue::kUPercent; case UnitType::kPixels: case UnitType::kCentimeters: case UnitType::kMillimeters: case UnitType::kQuarterMillimeters: case UnitType::kInches: case UnitType::kPoints: case UnitType::kPicas: case UnitType::kUserUnits: return CSSPrimitiveValue::kULength; case UnitType::kMilliseconds: case UnitType::kSeconds: return CSSPrimitiveValue::kUTime; case UnitType::kDegrees: case UnitType::kRadians: case UnitType::kGradians: case UnitType::kTurns: return CSSPrimitiveValue::kUAngle; case UnitType::kHertz: case UnitType::kKilohertz: return CSSPrimitiveValue::kUFrequency; case UnitType::kDotsPerPixel: case UnitType::kDotsPerInch: case UnitType::kDotsPerCentimeter: return CSSPrimitiveValue::kUResolution; default: return CSSPrimitiveValue::kUOther; } } bool CSSPrimitiveValue::IsCalculatedPercentageWithLength() const { // TODO(crbug.com/979895): Move this function to |CSSMathFunctionValue|. return IsCalculated() && To(this)->Category() == kCalcPercentLength; } bool CSSPrimitiveValue::IsResolution() const { // TODO(crbug.com/983613): Either support math functions on resolutions; or // provide a justification for not supporting it, and move this function to // |CSSNumericLiteralValue|. return IsNumericLiteralValue() && To(this)->IsResolution(); } bool CSSPrimitiveValue::IsFlex() const { // TODO(crbug.com/993136): Either support math functions on flexible lengths; // or provide a justification for not supporting it, and move this function to // |CSSNumericLiteralValue|. return IsNumericLiteralValue() && To(this)->IsFlex(); } bool CSSPrimitiveValue::IsAngle() const { if (IsNumericLiteralValue()) return To(this)->IsAngle(); return To(this)->IsAngle(); } bool CSSPrimitiveValue::IsLength() const { if (IsNumericLiteralValue()) return To(this)->IsLength(); return To(this)->IsLength(); } bool CSSPrimitiveValue::IsPx() const { if (IsNumericLiteralValue()) return To(this)->IsPx(); return To(this)->IsPx(); } bool CSSPrimitiveValue::IsNumber() const { if (IsNumericLiteralValue()) return To(this)->IsNumber(); return To(this)->IsNumber(); } bool CSSPrimitiveValue::IsInteger() const { // TODO(crbug.com/931216): Support integer math functions properly. return IsNumericLiteralValue() && To(this)->IsInteger(); } bool CSSPrimitiveValue::IsPercentage() const { if (IsNumericLiteralValue()) return To(this)->IsPercentage(); return To(this)->IsPercentage(); } bool CSSPrimitiveValue::IsTime() const { if (IsNumericLiteralValue()) return To(this)->IsTime(); return To(this)->IsTime(); } bool CSSPrimitiveValue::IsComputationallyIndependent() const { if (IsNumericLiteralValue()) return To(this)->IsComputationallyIndependent(); return To(this)->IsComputationallyIndependent(); } CSSPrimitiveValue::CSSPrimitiveValue(ClassType class_type) : CSSValue(class_type) {} // static CSSPrimitiveValue* CSSPrimitiveValue::CreateFromLength(const Length& length, float zoom) { switch (length.GetType()) { case Length::kPercent: return CSSNumericLiteralValue::Create(length.Percent(), UnitType::kPercentage); case Length::kFixed: return CSSNumericLiteralValue::Create(length.Value() / zoom, UnitType::kPixels); case Length::kCalculated: { const CalculationValue& calc = length.GetCalculationValue(); if (calc.IsExpression() || (calc.Pixels() && calc.Percent())) return CSSMathFunctionValue::Create(length, zoom); if (!calc.Pixels()) { double num = calc.Percent(); if (num < 0 && calc.IsNonNegative()) num = 0; return CSSNumericLiteralValue::Create(num, UnitType::kPercentage); } double num = calc.Pixels() / zoom; if (num < 0 && calc.IsNonNegative()) num = 0; return CSSNumericLiteralValue::Create(num, UnitType::kPixels); } default: break; } NOTREACHED(); return nullptr; } // TODO(crbug.com/1133390): When we support , we must clamp like //