/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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
 * OWNER OR CONTRIBUTORS 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 "core/css/resolver/StyleBuilderConverter.h"

#include "core/css/BasicShapeFunctions.h"
#include "core/css/CSSBasicShapeValues.h"
#include "core/css/CSSContentDistributionValue.h"
#include "core/css/CSSCustomIdentValue.h"
#include "core/css/CSSFontFamilyValue.h"
#include "core/css/CSSFontFeatureValue.h"
#include "core/css/CSSFunctionValue.h"
#include "core/css/CSSGridAutoRepeatValue.h"
#include "core/css/CSSGridLineNamesValue.h"
#include "core/css/CSSIdentifierValue.h"
#include "core/css/CSSPathValue.h"
#include "core/css/CSSPrimitiveValueMappings.h"
#include "core/css/CSSQuadValue.h"
#include "core/css/CSSReflectValue.h"
#include "core/css/CSSShadowValue.h"
#include "core/css/CSSStringValue.h"
#include "core/css/CSSURIValue.h"
#include "core/css/CSSValuePair.h"
#include "core/css/resolver/FilterOperationResolver.h"
#include "core/css/resolver/TransformBuilder.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/UseCounter.h"
#include "core/style/ClipPathOperation.h"
#include "core/style/TextSizeAdjust.h"
#include "core/svg/SVGURIReference.h"
#include "platform/fonts/FontCache.h"
#include "platform/transforms/RotateTransformOperation.h"
#include "platform/transforms/ScaleTransformOperation.h"
#include "platform/transforms/TranslateTransformOperation.h"
#include <algorithm>

namespace blink {

namespace {

static GridLength convertGridTrackBreadth(const StyleResolverState& state,
                                          const CSSValue& value) {
  // Fractional unit.
  if (value.isPrimitiveValue() && toCSSPrimitiveValue(value).isFlex())
    return GridLength(toCSSPrimitiveValue(value).getDoubleValue());

  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueMinContent)
    return Length(MinContent);

  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueMaxContent)
    return Length(MaxContent);

  return StyleBuilderConverter::convertLengthOrAuto(state, value);
}

}  // namespace

PassRefPtr<StyleReflection> StyleBuilderConverter::convertBoxReflect(
    StyleResolverState& state,
    const CSSValue& value) {
  if (value.isIdentifierValue()) {
    DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueNone);
    return ComputedStyle::initialBoxReflect();
  }

  const CSSReflectValue& reflectValue = toCSSReflectValue(value);
  RefPtr<StyleReflection> reflection = StyleReflection::create();
  reflection->setDirection(
      reflectValue.direction()->convertTo<CSSReflectionDirection>());
  if (reflectValue.offset())
    reflection->setOffset(reflectValue.offset()->convertToLength(
        state.cssToLengthConversionData()));
  if (reflectValue.mask()) {
    NinePieceImage mask;
    mask.setMaskDefaults();
    CSSToStyleMap::mapNinePieceImage(state, CSSPropertyWebkitBoxReflect,
                                     *reflectValue.mask(), mask);
    reflection->setMask(mask);
  }

  return reflection.release();
}

Color StyleBuilderConverter::convertColor(StyleResolverState& state,
                                          const CSSValue& value,
                                          bool forVisitedLink) {
  return state.document().textLinkColors().colorFromCSSValue(
      value, state.style()->color(), forVisitedLink);
}

AtomicString StyleBuilderConverter::convertFragmentIdentifier(
    StyleResolverState& state,
    const CSSValue& value) {
  if (value.isURIValue())
    return SVGURIReference::fragmentIdentifierFromIRIString(
        toCSSURIValue(value).value(), state.element()->treeScope());
  return nullAtom;
}

LengthBox StyleBuilderConverter::convertClip(StyleResolverState& state,
                                             const CSSValue& value) {
  const CSSQuadValue& rect = toCSSQuadValue(value);

  return LengthBox(convertLengthOrAuto(state, *rect.top()),
                   convertLengthOrAuto(state, *rect.right()),
                   convertLengthOrAuto(state, *rect.bottom()),
                   convertLengthOrAuto(state, *rect.left()));
}

PassRefPtr<ClipPathOperation> StyleBuilderConverter::convertClipPath(
    StyleResolverState& state,
    const CSSValue& value) {
  if (value.isBasicShapeValue())
    return ShapeClipPathOperation::create(basicShapeForValue(state, value));
  if (value.isURIValue()) {
    const CSSURIValue& urlValue = toCSSURIValue(value);
    SVGElementProxy& elementProxy =
        state.elementStyleResources().cachedOrPendingFromValue(urlValue);
    // TODO(fs): Doesn't work with external SVG references (crbug.com/109212.)
    return ReferenceClipPathOperation::create(urlValue.value(), elementProxy);
  }
  DCHECK(value.isIdentifierValue() &&
         toCSSIdentifierValue(value).getValueID() == CSSValueNone);
  return nullptr;
}

FilterOperations StyleBuilderConverter::convertFilterOperations(
    StyleResolverState& state,
    const CSSValue& value) {
  return FilterOperationResolver::createFilterOperations(state, value);
}

static FontDescription::GenericFamilyType convertGenericFamily(
    CSSValueID valueID) {
  switch (valueID) {
    case CSSValueWebkitBody:
      return FontDescription::StandardFamily;
    case CSSValueSerif:
      return FontDescription::SerifFamily;
    case CSSValueSansSerif:
      return FontDescription::SansSerifFamily;
    case CSSValueCursive:
      return FontDescription::CursiveFamily;
    case CSSValueFantasy:
      return FontDescription::FantasyFamily;
    case CSSValueMonospace:
      return FontDescription::MonospaceFamily;
    case CSSValueWebkitPictograph:
      return FontDescription::PictographFamily;
    default:
      return FontDescription::NoFamily;
  }
}

static bool convertFontFamilyName(
    StyleResolverState& state,
    const CSSValue& value,
    FontDescription::GenericFamilyType& genericFamily,
    AtomicString& familyName) {
  if (value.isFontFamilyValue()) {
    genericFamily = FontDescription::NoFamily;
    familyName = AtomicString(toCSSFontFamilyValue(value).value());
#if OS(MACOSX)
    if (familyName == FontCache::legacySystemFontFamily()) {
      UseCounter::count(state.document(), UseCounter::BlinkMacSystemFont);
      familyName = FontFamilyNames::system_ui;
    }
#endif
  } else if (state.document().settings()) {
    genericFamily =
        convertGenericFamily(toCSSIdentifierValue(value).getValueID());
    familyName = state.fontBuilder().genericFontFamilyName(genericFamily);
  }

  return !familyName.isEmpty();
}

FontDescription::FamilyDescription StyleBuilderConverter::convertFontFamily(
    StyleResolverState& state,
    const CSSValue& value) {
  ASSERT(value.isValueList());

  FontDescription::FamilyDescription desc(FontDescription::NoFamily);
  FontFamily* currFamily = nullptr;

  for (auto& family : toCSSValueList(value)) {
    FontDescription::GenericFamilyType genericFamily =
        FontDescription::NoFamily;
    AtomicString familyName;

    if (!convertFontFamilyName(state, *family, genericFamily, familyName))
      continue;

    if (!currFamily) {
      currFamily = &desc.family;
    } else {
      RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
      currFamily->appendFamily(newFamily);
      currFamily = newFamily.get();
    }

    currFamily->setFamily(familyName);

    if (genericFamily != FontDescription::NoFamily)
      desc.genericFamily = genericFamily;
  }

  return desc;
}

PassRefPtr<FontFeatureSettings>
StyleBuilderConverter::convertFontFeatureSettings(StyleResolverState& state,
                                                  const CSSValue& value) {
  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueNormal)
    return FontBuilder::initialFeatureSettings();

  const CSSValueList& list = toCSSValueList(value);
  RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
  int len = list.length();
  for (int i = 0; i < len; ++i) {
    const CSSFontFeatureValue& feature = toCSSFontFeatureValue(list.item(i));
    settings->append(FontFeature(feature.tag(), feature.value()));
  }
  return settings;
}

static float computeFontSize(StyleResolverState& state,
                             const CSSPrimitiveValue& primitiveValue,
                             const FontDescription::Size& parentSize) {
  if (primitiveValue.isLength())
    return primitiveValue.computeLength<float>(state.fontSizeConversionData());
  if (primitiveValue.isCalculatedPercentageWithLength())
    return primitiveValue.cssCalcValue()
        ->toCalcValue(state.fontSizeConversionData())
        ->evaluate(parentSize.value);

  ASSERT_NOT_REACHED();
  return 0;
}

FontDescription::Size StyleBuilderConverter::convertFontSize(
    StyleResolverState& state,
    const CSSValue& value) {
  FontDescription::Size parentSize(0, 0.0f, false);

  // FIXME: Find out when parentStyle could be 0?
  if (state.parentStyle())
    parentSize = state.parentFontDescription().getSize();

  if (value.isIdentifierValue()) {
    CSSValueID valueID = toCSSIdentifierValue(value).getValueID();
    if (FontSize::isValidValueID(valueID))
      return FontDescription::Size(FontSize::keywordSize(valueID), 0.0f, false);
    if (valueID == CSSValueSmaller)
      return FontDescription::smallerSize(parentSize);
    if (valueID == CSSValueLarger)
      return FontDescription::largerSize(parentSize);
    ASSERT_NOT_REACHED();
    return FontBuilder::initialSize();
  }

  bool parentIsAbsoluteSize = state.parentFontDescription().isAbsoluteSize();

  const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);
  if (primitiveValue.isPercentage())
    return FontDescription::Size(
        0, (primitiveValue.getFloatValue() * parentSize.value / 100.0f),
        parentIsAbsoluteSize);

  return FontDescription::Size(
      0, computeFontSize(state, primitiveValue, parentSize),
      parentIsAbsoluteSize || !primitiveValue.isFontRelativeLength());
}

float StyleBuilderConverter::convertFontSizeAdjust(StyleResolverState& state,
                                                   const CSSValue& value) {
  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueNone)
    return FontBuilder::initialSizeAdjust();

  const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);
  ASSERT(primitiveValue.isNumber());
  return primitiveValue.getFloatValue();
}

FontWeight StyleBuilderConverter::convertFontWeight(StyleResolverState& state,
                                                    const CSSValue& value) {
  const CSSIdentifierValue& identifierValue = toCSSIdentifierValue(value);
  switch (identifierValue.getValueID()) {
    case CSSValueBolder:
      return FontDescription::bolderWeight(
          state.parentStyle()->getFontDescription().weight());
    case CSSValueLighter:
      return FontDescription::lighterWeight(
          state.parentStyle()->getFontDescription().weight());
    default:
      return identifierValue.convertTo<FontWeight>();
  }
}

FontDescription::FontVariantCaps StyleBuilderConverter::convertFontVariantCaps(
    StyleResolverState&,
    const CSSValue& value) {
  SECURITY_DCHECK(value.isIdentifierValue());
  CSSValueID valueID = toCSSIdentifierValue(value).getValueID();
  switch (valueID) {
    case CSSValueNormal:
      return FontDescription::CapsNormal;
    case CSSValueSmallCaps:
      return FontDescription::SmallCaps;
    case CSSValueAllSmallCaps:
      return FontDescription::AllSmallCaps;
    case CSSValuePetiteCaps:
      return FontDescription::PetiteCaps;
    case CSSValueAllPetiteCaps:
      return FontDescription::AllPetiteCaps;
    case CSSValueUnicase:
      return FontDescription::Unicase;
    case CSSValueTitlingCaps:
      return FontDescription::TitlingCaps;
    default:
      return FontDescription::CapsNormal;
  }
}

FontDescription::VariantLigatures
StyleBuilderConverter::convertFontVariantLigatures(StyleResolverState&,
                                                   const CSSValue& value) {
  if (value.isValueList()) {
    FontDescription::VariantLigatures ligatures;
    const CSSValueList& valueList = toCSSValueList(value);
    for (size_t i = 0; i < valueList.length(); ++i) {
      const CSSValue& item = valueList.item(i);
      switch (toCSSIdentifierValue(item).getValueID()) {
        case CSSValueNoCommonLigatures:
          ligatures.common = FontDescription::DisabledLigaturesState;
          break;
        case CSSValueCommonLigatures:
          ligatures.common = FontDescription::EnabledLigaturesState;
          break;
        case CSSValueNoDiscretionaryLigatures:
          ligatures.discretionary = FontDescription::DisabledLigaturesState;
          break;
        case CSSValueDiscretionaryLigatures:
          ligatures.discretionary = FontDescription::EnabledLigaturesState;
          break;
        case CSSValueNoHistoricalLigatures:
          ligatures.historical = FontDescription::DisabledLigaturesState;
          break;
        case CSSValueHistoricalLigatures:
          ligatures.historical = FontDescription::EnabledLigaturesState;
          break;
        case CSSValueNoContextual:
          ligatures.contextual = FontDescription::DisabledLigaturesState;
          break;
        case CSSValueContextual:
          ligatures.contextual = FontDescription::EnabledLigaturesState;
          break;
        default:
          ASSERT_NOT_REACHED();
          break;
      }
    }
    return ligatures;
  }

  SECURITY_DCHECK(value.isIdentifierValue());
  if (toCSSIdentifierValue(value).getValueID() == CSSValueNone) {
    return FontDescription::VariantLigatures(
        FontDescription::DisabledLigaturesState);
  }

  DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueNormal);
  return FontDescription::VariantLigatures();
}

FontVariantNumeric StyleBuilderConverter::convertFontVariantNumeric(
    StyleResolverState&,
    const CSSValue& value) {
  if (value.isIdentifierValue()) {
    DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueNormal);
    return FontVariantNumeric();
  }

  FontVariantNumeric variantNumeric;
  for (const CSSValue* feature : toCSSValueList(value)) {
    switch (toCSSIdentifierValue(feature)->getValueID()) {
      case CSSValueLiningNums:
        variantNumeric.setNumericFigure(FontVariantNumeric::LiningNums);
        break;
      case CSSValueOldstyleNums:
        variantNumeric.setNumericFigure(FontVariantNumeric::OldstyleNums);
        break;
      case CSSValueProportionalNums:
        variantNumeric.setNumericSpacing(FontVariantNumeric::ProportionalNums);
        break;
      case CSSValueTabularNums:
        variantNumeric.setNumericSpacing(FontVariantNumeric::TabularNums);
        break;
      case CSSValueDiagonalFractions:
        variantNumeric.setNumericFraction(
            FontVariantNumeric::DiagonalFractions);
        break;
      case CSSValueStackedFractions:
        variantNumeric.setNumericFraction(FontVariantNumeric::StackedFractions);
        break;
      case CSSValueOrdinal:
        variantNumeric.setOrdinal(FontVariantNumeric::OrdinalOn);
        break;
      case CSSValueSlashedZero:
        variantNumeric.setSlashedZero(FontVariantNumeric::SlashedZeroOn);
        break;
      default:
        ASSERT_NOT_REACHED();
        break;
    }
  }
  return variantNumeric;
}

StyleSelfAlignmentData StyleBuilderConverter::convertSelfOrDefaultAlignmentData(
    StyleResolverState&,
    const CSSValue& value) {
  StyleSelfAlignmentData alignmentData = ComputedStyle::initialSelfAlignment();
  if (value.isValuePair()) {
    const CSSValuePair& pair = toCSSValuePair(value);
    if (toCSSIdentifierValue(pair.first()).getValueID() == CSSValueLegacy) {
      alignmentData.setPositionType(LegacyPosition);
      alignmentData.setPosition(
          toCSSIdentifierValue(pair.second()).convertTo<ItemPosition>());
    } else {
      alignmentData.setPosition(
          toCSSIdentifierValue(pair.first()).convertTo<ItemPosition>());
      alignmentData.setOverflow(
          toCSSIdentifierValue(pair.second()).convertTo<OverflowAlignment>());
    }
  } else {
    alignmentData.setPosition(
        toCSSIdentifierValue(value).convertTo<ItemPosition>());
  }
  return alignmentData;
}

StyleContentAlignmentData StyleBuilderConverter::convertContentAlignmentData(
    StyleResolverState&,
    const CSSValue& value) {
  StyleContentAlignmentData alignmentData =
      ComputedStyle::initialContentAlignment();
  if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) {
    const CSSIdentifierValue& identifierValue = toCSSIdentifierValue(value);
    switch (identifierValue.getValueID()) {
      case CSSValueStretch:
      case CSSValueSpaceBetween:
      case CSSValueSpaceAround:
        alignmentData.setDistribution(
            identifierValue.convertTo<ContentDistributionType>());
        break;
      case CSSValueFlexStart:
      case CSSValueFlexEnd:
      case CSSValueCenter:
        alignmentData.setPosition(identifierValue.convertTo<ContentPosition>());
        break;
      default:
        ASSERT_NOT_REACHED();
    }
    return alignmentData;
  }
  const CSSContentDistributionValue& contentValue =
      toCSSContentDistributionValue(value);
  if (contentValue.distribution()->getValueID() != CSSValueInvalid)
    alignmentData.setDistribution(
        contentValue.distribution()->convertTo<ContentDistributionType>());
  if (contentValue.position()->getValueID() != CSSValueInvalid)
    alignmentData.setPosition(
        contentValue.position()->convertTo<ContentPosition>());
  if (contentValue.overflow()->getValueID() != CSSValueInvalid)
    alignmentData.setOverflow(
        contentValue.overflow()->convertTo<OverflowAlignment>());
  return alignmentData;
}

GridAutoFlow StyleBuilderConverter::convertGridAutoFlow(StyleResolverState&,
                                                        const CSSValue& value) {
  const CSSValueList& list = toCSSValueList(value);

  ASSERT(list.length() >= 1);
  const CSSIdentifierValue& first = toCSSIdentifierValue(list.item(0));
  const CSSIdentifierValue* second =
      list.length() == 2 ? &toCSSIdentifierValue(list.item(1)) : nullptr;

  switch (first.getValueID()) {
    case CSSValueRow:
      if (second && second->getValueID() == CSSValueDense)
        return AutoFlowRowDense;
      return AutoFlowRow;
    case CSSValueColumn:
      if (second && second->getValueID() == CSSValueDense)
        return AutoFlowColumnDense;
      return AutoFlowColumn;
    case CSSValueDense:
      if (second && second->getValueID() == CSSValueColumn)
        return AutoFlowColumnDense;
      return AutoFlowRowDense;
    default:
      ASSERT_NOT_REACHED();
      return ComputedStyle::initialGridAutoFlow();
  }
}

GridPosition StyleBuilderConverter::convertGridPosition(StyleResolverState&,
                                                        const CSSValue& value) {
  // We accept the specification's grammar:
  // 'auto' | [ <integer> || <custom-ident> ] |
  // [ span && [ <integer> || <custom-ident> ] ] | <custom-ident>

  GridPosition position;

  if (value.isCustomIdentValue()) {
    position.setNamedGridArea(toCSSCustomIdentValue(value).value());
    return position;
  }

  if (value.isIdentifierValue()) {
    DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueAuto);
    return position;
  }

  const CSSValueList& values = toCSSValueList(value);
  ASSERT(values.length());

  bool isSpanPosition = false;
  // The specification makes the <integer> optional, in which case it default to
  // '1'.
  int gridLineNumber = 1;
  AtomicString gridLineName;

  auto it = values.begin();
  const CSSValue* currentValue = it->get();
  if (currentValue->isIdentifierValue() &&
      toCSSIdentifierValue(currentValue)->getValueID() == CSSValueSpan) {
    isSpanPosition = true;
    ++it;
    currentValue = it != values.end() ? it->get() : nullptr;
  }

  if (currentValue && currentValue->isPrimitiveValue() &&
      toCSSPrimitiveValue(currentValue)->isNumber()) {
    gridLineNumber = toCSSPrimitiveValue(currentValue)->getIntValue();
    ++it;
    currentValue = it != values.end() ? it->get() : nullptr;
  }

  if (currentValue && currentValue->isCustomIdentValue()) {
    gridLineName = toCSSCustomIdentValue(currentValue)->value();
    ++it;
  }

  ASSERT(it == values.end());
  if (isSpanPosition)
    position.setSpanPosition(gridLineNumber, gridLineName);
  else
    position.setExplicitPosition(gridLineNumber, gridLineName);

  return position;
}

GridTrackSize StyleBuilderConverter::convertGridTrackSize(
    StyleResolverState& state,
    const CSSValue& value) {
  if (value.isPrimitiveValue() || value.isIdentifierValue())
    return GridTrackSize(convertGridTrackBreadth(state, value));

  auto& function = toCSSFunctionValue(value);
  if (function.functionType() == CSSValueFitContent) {
    SECURITY_DCHECK(function.length() == 1);
    return GridTrackSize(convertGridTrackBreadth(state, function.item(0)),
                         FitContentTrackSizing);
  }

  SECURITY_DCHECK(function.length() == 2);
  GridLength minTrackBreadth(convertGridTrackBreadth(state, function.item(0)));
  GridLength maxTrackBreadth(convertGridTrackBreadth(state, function.item(1)));
  return GridTrackSize(minTrackBreadth, maxTrackBreadth);
}

static void convertGridLineNamesList(
    const CSSValue& value,
    size_t currentNamedGridLine,
    NamedGridLinesMap& namedGridLines,
    OrderedNamedGridLines& orderedNamedGridLines) {
  ASSERT(value.isGridLineNamesValue());

  for (auto& namedGridLineValue : toCSSValueList(value)) {
    String namedGridLine = toCSSCustomIdentValue(*namedGridLineValue).value();
    NamedGridLinesMap::AddResult result =
        namedGridLines.add(namedGridLine, Vector<size_t>());
    result.storedValue->value.append(currentNamedGridLine);
    OrderedNamedGridLines::AddResult orderedInsertionResult =
        orderedNamedGridLines.add(currentNamedGridLine, Vector<String>());
    orderedInsertionResult.storedValue->value.append(namedGridLine);
  }
}

Vector<GridTrackSize> StyleBuilderConverter::convertGridTrackSizeList(
    StyleResolverState& state,
    const CSSValue& value) {
  DCHECK(value.isValueList());
  Vector<GridTrackSize> trackSizes;
  for (auto& currValue : toCSSValueList(value)) {
    DCHECK(!currValue->isGridLineNamesValue());
    DCHECK(!currValue->isGridAutoRepeatValue());
    trackSizes.append(convertGridTrackSize(state, *currValue));
  }
  return trackSizes;
}

void StyleBuilderConverter::convertGridTrackList(
    const CSSValue& value,
    Vector<GridTrackSize>& trackSizes,
    NamedGridLinesMap& namedGridLines,
    OrderedNamedGridLines& orderedNamedGridLines,
    Vector<GridTrackSize>& autoRepeatTrackSizes,
    NamedGridLinesMap& autoRepeatNamedGridLines,
    OrderedNamedGridLines& autoRepeatOrderedNamedGridLines,
    size_t& autoRepeatInsertionPoint,
    AutoRepeatType& autoRepeatType,
    StyleResolverState& state) {
  if (value.isIdentifierValue()) {
    DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueNone);
    return;
  }

  size_t currentNamedGridLine = 0;
  for (auto currValue : toCSSValueList(value)) {
    if (currValue->isGridLineNamesValue()) {
      convertGridLineNamesList(*currValue, currentNamedGridLine, namedGridLines,
                               orderedNamedGridLines);
      continue;
    }

    if (currValue->isGridAutoRepeatValue()) {
      ASSERT(autoRepeatTrackSizes.isEmpty());
      size_t autoRepeatIndex = 0;
      CSSValueID autoRepeatID =
          toCSSGridAutoRepeatValue(currValue.get())->autoRepeatID();
      ASSERT(autoRepeatID == CSSValueAutoFill ||
             autoRepeatID == CSSValueAutoFit);
      autoRepeatType = autoRepeatID == CSSValueAutoFill ? AutoFill : AutoFit;
      for (auto autoRepeatValue : toCSSValueList(*currValue)) {
        if (autoRepeatValue->isGridLineNamesValue()) {
          convertGridLineNamesList(*autoRepeatValue, autoRepeatIndex,
                                   autoRepeatNamedGridLines,
                                   autoRepeatOrderedNamedGridLines);
          continue;
        }
        ++autoRepeatIndex;
        autoRepeatTrackSizes.append(
            convertGridTrackSize(state, *autoRepeatValue));
      }
      autoRepeatInsertionPoint = currentNamedGridLine++;
      continue;
    }

    ++currentNamedGridLine;
    trackSizes.append(convertGridTrackSize(state, *currValue));
  }

  // The parser should have rejected any <track-list> without any <track-size>
  // as this is not conformant to the syntax.
  ASSERT(!trackSizes.isEmpty() || !autoRepeatTrackSizes.isEmpty());
}

void StyleBuilderConverter::convertOrderedNamedGridLinesMapToNamedGridLinesMap(
    const OrderedNamedGridLines& orderedNamedGridLines,
    NamedGridLinesMap& namedGridLines) {
  ASSERT(namedGridLines.size() == 0);

  if (orderedNamedGridLines.size() == 0)
    return;

  for (auto& orderedNamedGridLine : orderedNamedGridLines) {
    for (auto& lineName : orderedNamedGridLine.value) {
      NamedGridLinesMap::AddResult startResult =
          namedGridLines.add(lineName, Vector<size_t>());
      startResult.storedValue->value.append(orderedNamedGridLine.key);
    }
  }

  for (auto& namedGridLine : namedGridLines) {
    Vector<size_t> gridLineIndexes = namedGridLine.value;
    std::sort(gridLineIndexes.begin(), gridLineIndexes.end());
  }
}

void StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(
    const NamedGridAreaMap& namedGridAreas,
    NamedGridLinesMap& namedGridLines,
    GridTrackSizingDirection direction) {
  for (const auto& namedGridAreaEntry : namedGridAreas) {
    GridSpan areaSpan = direction == ForRows ? namedGridAreaEntry.value.rows
                                             : namedGridAreaEntry.value.columns;
    {
      NamedGridLinesMap::AddResult startResult = namedGridLines.add(
          namedGridAreaEntry.key + "-start", Vector<size_t>());
      startResult.storedValue->value.append(areaSpan.startLine());
      std::sort(startResult.storedValue->value.begin(),
                startResult.storedValue->value.end());
    }
    {
      NamedGridLinesMap::AddResult endResult =
          namedGridLines.add(namedGridAreaEntry.key + "-end", Vector<size_t>());
      endResult.storedValue->value.append(areaSpan.endLine());
      std::sort(endResult.storedValue->value.begin(),
                endResult.storedValue->value.end());
    }
  }
}

Length StyleBuilderConverter::convertLength(const StyleResolverState& state,
                                            const CSSValue& value) {
  return toCSSPrimitiveValue(value).convertToLength(
      state.cssToLengthConversionData());
}

UnzoomedLength StyleBuilderConverter::convertUnzoomedLength(
    const StyleResolverState& state,
    const CSSValue& value) {
  return UnzoomedLength(toCSSPrimitiveValue(value).convertToLength(
      state.cssToLengthConversionData().copyWithAdjustedZoom(1.0f)));
}

Length StyleBuilderConverter::convertLengthOrAuto(
    const StyleResolverState& state,
    const CSSValue& value) {
  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueAuto)
    return Length(Auto);
  return toCSSPrimitiveValue(value).convertToLength(
      state.cssToLengthConversionData());
}

Length StyleBuilderConverter::convertLengthSizing(StyleResolverState& state,
                                                  const CSSValue& value) {
  if (!value.isIdentifierValue())
    return convertLength(state, value);

  const CSSIdentifierValue& identifierValue = toCSSIdentifierValue(value);
  switch (identifierValue.getValueID()) {
    case CSSValueMinContent:
    case CSSValueWebkitMinContent:
      return Length(MinContent);
    case CSSValueMaxContent:
    case CSSValueWebkitMaxContent:
      return Length(MaxContent);
    case CSSValueWebkitFillAvailable:
      return Length(FillAvailable);
    case CSSValueWebkitFitContent:
    case CSSValueFitContent:
      return Length(FitContent);
    case CSSValueAuto:
      return Length(Auto);
    default:
      ASSERT_NOT_REACHED();
      return Length();
  }
}

Length StyleBuilderConverter::convertLengthMaxSizing(StyleResolverState& state,
                                                     const CSSValue& value) {
  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueNone)
    return Length(MaxSizeNone);
  return convertLengthSizing(state, value);
}

TabSize StyleBuilderConverter::convertLengthOrTabSpaces(
    StyleResolverState& state,
    const CSSValue& value) {
  const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);
  if (primitiveValue.isNumber())
    return TabSize(primitiveValue.getIntValue());
  return TabSize(
      primitiveValue.computeLength<float>(state.cssToLengthConversionData()));
}

static CSSToLengthConversionData lineHeightToLengthConversionData(
    StyleResolverState& state) {
  float multiplier = state.style()->effectiveZoom();
  if (LocalFrame* frame = state.document().frame())
    multiplier *= frame->textZoomFactor();
  return state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier);
}

Length StyleBuilderConverter::convertLineHeight(StyleResolverState& state,
                                                const CSSValue& value) {
  if (value.isPrimitiveValue()) {
    const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);
    if (primitiveValue.isLength()) {
      return primitiveValue.computeLength<Length>(
          lineHeightToLengthConversionData(state));
    }
    if (primitiveValue.isPercentage()) {
      return Length(
          (state.style()->computedFontSize() * primitiveValue.getIntValue()) /
              100.0,
          Fixed);
    }
    if (primitiveValue.isNumber())
      return Length(primitiveValue.getDoubleValue() * 100.0, Percent);
    if (primitiveValue.isCalculated()) {
      Length zoomedLength = Length(primitiveValue.cssCalcValue()->toCalcValue(
          lineHeightToLengthConversionData(state)));
      return Length(
          valueForLength(zoomedLength,
                         LayoutUnit(state.style()->computedFontSize())),
          Fixed);
    }
  }

  DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueNormal);
  return ComputedStyle::initialLineHeight();
}

float StyleBuilderConverter::convertNumberOrPercentage(
    StyleResolverState& state,
    const CSSValue& value) {
  const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);
  ASSERT(primitiveValue.isNumber() || primitiveValue.isPercentage());
  if (primitiveValue.isNumber())
    return primitiveValue.getFloatValue();
  return primitiveValue.getFloatValue() / 100.0f;
}

StyleOffsetRotation StyleBuilderConverter::convertOffsetRotation(
    StyleResolverState&,
    const CSSValue& value) {
  return convertOffsetRotation(value);
}

StyleOffsetRotation StyleBuilderConverter::convertOffsetRotation(
    const CSSValue& value) {
  StyleOffsetRotation result(0, OffsetRotationFixed);

  const CSSValueList& list = toCSSValueList(value);
  ASSERT(list.length() == 1 || list.length() == 2);
  for (const auto& item : list) {
    if (item->isIdentifierValue() &&
        toCSSIdentifierValue(*item).getValueID() == CSSValueAuto) {
      result.type = OffsetRotationAuto;
    } else if (item->isIdentifierValue() &&
               toCSSIdentifierValue(*item).getValueID() == CSSValueReverse) {
      result.type = OffsetRotationAuto;
      result.angle += 180;
    } else {
      const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(*item);
      result.angle += primitiveValue.computeDegrees();
    }
  }
  result.angle = clampTo<float>(result.angle);

  return result;
}

template <CSSValueID cssValueFor0, CSSValueID cssValueFor100>
Length StyleBuilderConverter::convertPositionLength(StyleResolverState& state,
                                                    const CSSValue& value) {
  if (value.isValuePair()) {
    const CSSValuePair& pair = toCSSValuePair(value);
    Length length = StyleBuilderConverter::convertLength(state, pair.second());
    if (toCSSIdentifierValue(pair.first()).getValueID() == cssValueFor0)
      return length;
    DCHECK_EQ(toCSSIdentifierValue(pair.first()).getValueID(), cssValueFor100);
    return length.subtractFromOneHundredPercent();
  }

  if (value.isIdentifierValue()) {
    switch (toCSSIdentifierValue(value).getValueID()) {
      case cssValueFor0:
        return Length(0, Percent);
      case cssValueFor100:
        return Length(100, Percent);
      case CSSValueCenter:
        return Length(50, Percent);
      default:
        ASSERT_NOT_REACHED();
    }
  }

  return StyleBuilderConverter::convertLength(state,
                                              toCSSPrimitiveValue(value));
}

LengthPoint StyleBuilderConverter::convertPosition(StyleResolverState& state,
                                                   const CSSValue& value) {
  const CSSValuePair& pair = toCSSValuePair(value);
  return LengthPoint(
      convertPositionLength<CSSValueLeft, CSSValueRight>(state, pair.first()),
      convertPositionLength<CSSValueTop, CSSValueBottom>(state, pair.second()));
}

LengthPoint StyleBuilderConverter::convertPositionOrAuto(
    StyleResolverState& state,
    const CSSValue& value) {
  if (value.isValuePair())
    return convertPosition(state, value);
  DCHECK(toCSSIdentifierValue(value).getValueID() == CSSValueAuto);
  return LengthPoint(Length(Auto), Length(Auto));
}

static float convertPerspectiveLength(StyleResolverState& state,
                                      const CSSPrimitiveValue& primitiveValue) {
  return std::max(
      primitiveValue.computeLength<float>(state.cssToLengthConversionData()),
      0.0f);
}

float StyleBuilderConverter::convertPerspective(StyleResolverState& state,
                                                const CSSValue& value) {
  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueNone)
    return ComputedStyle::initialPerspective();
  return convertPerspectiveLength(state, toCSSPrimitiveValue(value));
}

EPaintOrder StyleBuilderConverter::convertPaintOrder(
    StyleResolverState&,
    const CSSValue& cssPaintOrder) {
  if (cssPaintOrder.isValueList()) {
    const CSSValueList& orderTypeList = toCSSValueList(cssPaintOrder);
    switch (toCSSIdentifierValue(orderTypeList.item(0)).getValueID()) {
      case CSSValueFill:
        return orderTypeList.length() > 1 ? PaintOrderFillMarkersStroke
                                          : PaintOrderFillStrokeMarkers;
      case CSSValueStroke:
        return orderTypeList.length() > 1 ? PaintOrderStrokeMarkersFill
                                          : PaintOrderStrokeFillMarkers;
      case CSSValueMarkers:
        return orderTypeList.length() > 1 ? PaintOrderMarkersStrokeFill
                                          : PaintOrderMarkersFillStroke;
      default:
        ASSERT_NOT_REACHED();
        return PaintOrderNormal;
    }
  }

  return PaintOrderNormal;
}

Length StyleBuilderConverter::convertQuirkyLength(StyleResolverState& state,
                                                  const CSSValue& value) {
  Length length = convertLengthOrAuto(state, value);
  // This is only for margins which use __qem
  length.setQuirk(value.isPrimitiveValue() &&
                  toCSSPrimitiveValue(value).isQuirkyEms());
  return length;
}

PassRefPtr<QuotesData> StyleBuilderConverter::convertQuotes(
    StyleResolverState&,
    const CSSValue& value) {
  if (value.isValueList()) {
    const CSSValueList& list = toCSSValueList(value);
    RefPtr<QuotesData> quotes = QuotesData::create();
    for (size_t i = 0; i < list.length(); i += 2) {
      String startQuote = toCSSStringValue(list.item(i)).value();
      String endQuote = toCSSStringValue(list.item(i + 1)).value();
      quotes->addPair(std::make_pair(startQuote, endQuote));
    }
    return quotes.release();
  }
  DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueNone);
  return QuotesData::create();
}

LengthSize StyleBuilderConverter::convertRadius(StyleResolverState& state,
                                                const CSSValue& value) {
  const CSSValuePair& pair = toCSSValuePair(value);
  Length radiusWidth = toCSSPrimitiveValue(pair.first())
                           .convertToLength(state.cssToLengthConversionData());
  Length radiusHeight = toCSSPrimitiveValue(pair.second())
                            .convertToLength(state.cssToLengthConversionData());
  return LengthSize(radiusWidth, radiusHeight);
}

PassRefPtr<ShadowList> StyleBuilderConverter::convertShadow(
    StyleResolverState& state,
    const CSSValue& value) {
  if (value.isIdentifierValue()) {
    DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueNone);
    return PassRefPtr<ShadowList>();
  }

  const CSSValueList& valueList = toCSSValueList(value);
  size_t shadowCount = valueList.length();
  ShadowDataVector shadows;
  for (size_t i = 0; i < shadowCount; ++i) {
    const CSSShadowValue& item = toCSSShadowValue(valueList.item(i));
    float x = item.x->computeLength<float>(state.cssToLengthConversionData());
    float y = item.y->computeLength<float>(state.cssToLengthConversionData());
    float blur =
        item.blur
            ? item.blur->computeLength<float>(state.cssToLengthConversionData())
            : 0;
    float spread = item.spread
                       ? item.spread->computeLength<float>(
                             state.cssToLengthConversionData())
                       : 0;
    ShadowStyle shadowStyle =
        item.style && item.style->getValueID() == CSSValueInset ? Inset
                                                                : Normal;
    StyleColor color = StyleColor::currentColor();
    if (item.color)
      color = convertStyleColor(state, *item.color);
    shadows.append(
        ShadowData(FloatPoint(x, y), blur, spread, shadowStyle, color));
  }
  return ShadowList::adopt(shadows);
}

ShapeValue* StyleBuilderConverter::convertShapeValue(StyleResolverState& state,
                                                     const CSSValue& value) {
  if (value.isIdentifierValue()) {
    DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueNone);
    return nullptr;
  }

  if (value.isImageValue() || value.isImageGeneratorValue() ||
      value.isImageSetValue())
    return ShapeValue::createImageValue(
        state.styleImage(CSSPropertyShapeOutside, value));

  RefPtr<BasicShape> shape;
  CSSBoxType cssBox = BoxMissing;
  const CSSValueList& valueList = toCSSValueList(value);
  for (unsigned i = 0; i < valueList.length(); ++i) {
    const CSSValue& value = valueList.item(i);
    if (value.isBasicShapeValue()) {
      shape = basicShapeForValue(state, value);
    } else {
      cssBox = toCSSIdentifierValue(value).convertTo<CSSBoxType>();
    }
  }

  if (shape)
    return ShapeValue::createShapeValue(shape.release(), cssBox);

  ASSERT(cssBox != BoxMissing);
  return ShapeValue::createBoxShapeValue(cssBox);
}

float StyleBuilderConverter::convertSpacing(StyleResolverState& state,
                                            const CSSValue& value) {
  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueNormal)
    return 0;
  return toCSSPrimitiveValue(value).computeLength<float>(
      state.cssToLengthConversionData());
}

PassRefPtr<SVGDashArray> StyleBuilderConverter::convertStrokeDasharray(
    StyleResolverState& state,
    const CSSValue& value) {
  if (!value.isValueList())
    return SVGComputedStyle::initialStrokeDashArray();

  const CSSValueList& dashes = toCSSValueList(value);

  RefPtr<SVGDashArray> array = SVGDashArray::create();
  size_t length = dashes.length();
  for (size_t i = 0; i < length; ++i) {
    array->append(convertLength(state, toCSSPrimitiveValue(dashes.item(i))));
  }

  return array.release();
}

StyleColor StyleBuilderConverter::convertStyleColor(StyleResolverState& state,
                                                    const CSSValue& value,
                                                    bool forVisitedLink) {
  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueCurrentcolor)
    return StyleColor::currentColor();
  return state.document().textLinkColors().colorFromCSSValue(value, Color(),
                                                             forVisitedLink);
}

float StyleBuilderConverter::convertTextStrokeWidth(StyleResolverState& state,
                                                    const CSSValue& value) {
  if (value.isIdentifierValue() && toCSSIdentifierValue(value).getValueID()) {
    float multiplier = convertLineWidth<float>(state, value);
    return CSSPrimitiveValue::create(multiplier / 48,
                                     CSSPrimitiveValue::UnitType::Ems)
        ->computeLength<float>(state.cssToLengthConversionData());
  }
  return toCSSPrimitiveValue(value).computeLength<float>(
      state.cssToLengthConversionData());
}

TextSizeAdjust StyleBuilderConverter::convertTextSizeAdjust(
    StyleResolverState& state,
    const CSSValue& value) {
  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueNone)
    return TextSizeAdjust::adjustNone();
  if (value.isIdentifierValue() &&
      toCSSIdentifierValue(value).getValueID() == CSSValueAuto)
    return TextSizeAdjust::adjustAuto();
  const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);
  DCHECK(primitiveValue.isPercentage());
  return TextSizeAdjust(primitiveValue.getFloatValue() / 100.0f);
}

TransformOperations StyleBuilderConverter::convertTransformOperations(
    StyleResolverState& state,
    const CSSValue& value) {
  return TransformBuilder::createTransformOperations(
      value, state.cssToLengthConversionData());
}

TransformOrigin StyleBuilderConverter::convertTransformOrigin(
    StyleResolverState& state,
    const CSSValue& value) {
  const CSSValueList& list = toCSSValueList(value);
  DCHECK_EQ(list.length(), 3U);
  DCHECK(list.item(0).isPrimitiveValue() || list.item(0).isIdentifierValue());
  DCHECK(list.item(1).isPrimitiveValue() || list.item(1).isIdentifierValue());
  DCHECK(list.item(2).isPrimitiveValue());

  return TransformOrigin(
      convertPositionLength<CSSValueLeft, CSSValueRight>(state, list.item(0)),
      convertPositionLength<CSSValueTop, CSSValueBottom>(state, list.item(1)),
      StyleBuilderConverter::convertComputedLength<float>(state, list.item(2)));
}

ScrollSnapPoints StyleBuilderConverter::convertSnapPoints(
    StyleResolverState& state,
    const CSSValue& value) {
  // Handles: none | repeat(<length>)
  ScrollSnapPoints points;
  points.hasRepeat = false;

  if (!value.isFunctionValue())
    return points;

  const CSSFunctionValue& repeatFunction = toCSSFunctionValue(value);
  SECURITY_DCHECK(repeatFunction.length() == 1);
  points.repeatOffset =
      convertLength(state, toCSSPrimitiveValue(repeatFunction.item(0)));
  points.hasRepeat = true;

  return points;
}

Vector<LengthPoint> StyleBuilderConverter::convertSnapCoordinates(
    StyleResolverState& state,
    const CSSValue& value) {
  // Handles: none | <position>#
  Vector<LengthPoint> coordinates;

  if (!value.isValueList())
    return coordinates;

  const CSSValueList& valueList = toCSSValueList(value);
  coordinates.reserveInitialCapacity(valueList.length());
  for (auto& snapCoordinate : valueList) {
    coordinates.uncheckedAppend(convertPosition(state, *snapCoordinate));
  }

  return coordinates;
}

PassRefPtr<TranslateTransformOperation> StyleBuilderConverter::convertTranslate(
    StyleResolverState& state,
    const CSSValue& value) {
  const CSSValueList& list = toCSSValueList(value);
  ASSERT(list.length() <= 3);
  Length tx = convertLength(state, list.item(0));
  Length ty(0, Fixed);
  double tz = 0;
  if (list.length() >= 2)
    ty = convertLength(state, list.item(1));
  if (list.length() == 3)
    tz = toCSSPrimitiveValue(list.item(2))
             .computeLength<double>(state.cssToLengthConversionData());

  return TranslateTransformOperation::create(tx, ty, tz,
                                             TransformOperation::Translate3D);
}

Rotation StyleBuilderConverter::convertRotation(const CSSValue& value) {
  const CSSValueList& list = toCSSValueList(value);
  ASSERT(list.length() == 1 || list.length() == 4);
  double angle = toCSSPrimitiveValue(list.item(0)).computeDegrees();
  double x = 0;
  double y = 0;
  double z = 1;
  if (list.length() == 4) {
    x = toCSSPrimitiveValue(list.item(1)).getDoubleValue();
    y = toCSSPrimitiveValue(list.item(2)).getDoubleValue();
    z = toCSSPrimitiveValue(list.item(3)).getDoubleValue();
  }
  return Rotation(FloatPoint3D(x, y, z), angle);
}

PassRefPtr<RotateTransformOperation> StyleBuilderConverter::convertRotate(
    StyleResolverState& state,
    const CSSValue& value) {
  return RotateTransformOperation::create(convertRotation(value),
                                          TransformOperation::Rotate3D);
}

PassRefPtr<ScaleTransformOperation> StyleBuilderConverter::convertScale(
    StyleResolverState& state,
    const CSSValue& value) {
  const CSSValueList& list = toCSSValueList(value);
  ASSERT(list.length() <= 3);
  double sx = toCSSPrimitiveValue(list.item(0)).getDoubleValue();
  double sy = sx;
  double sz = 1;
  if (list.length() >= 2)
    sy = toCSSPrimitiveValue(list.item(1)).getDoubleValue();
  if (list.length() == 3)
    sz = toCSSPrimitiveValue(list.item(2)).getDoubleValue();

  return ScaleTransformOperation::create(sx, sy, sz,
                                         TransformOperation::Scale3D);
}

RespectImageOrientationEnum StyleBuilderConverter::convertImageOrientation(
    StyleResolverState& state,
    const CSSValue& value) {
  return value.isIdentifierValue() &&
                 toCSSIdentifierValue(value).getValueID() == CSSValueFromImage
             ? RespectImageOrientation
             : DoNotRespectImageOrientation;
}

PassRefPtr<StylePath> StyleBuilderConverter::convertPathOrNone(
    StyleResolverState& state,
    const CSSValue& value) {
  if (value.isPathValue())
    return toCSSPathValue(value).stylePath();
  DCHECK_EQ(toCSSIdentifierValue(value).getValueID(), CSSValueNone);
  return nullptr;
}

const CSSValue& StyleBuilderConverter::convertRegisteredPropertyValue(
    const StyleResolverState& state,
    const CSSValue& value) {
  // TODO(timloh): Images and transform-function values can also contain
  // lengths.
  if (value.isValueList()) {
    CSSValueList* newList = CSSValueList::createSpaceSeparated();
    for (const CSSValue* innerValue : toCSSValueList(value))
      newList->append(convertRegisteredPropertyValue(state, *innerValue));
    return *newList;
  }

  if (value.isPrimitiveValue()) {
    const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);
    if (primitiveValue.isCalculated() ||
        CSSPrimitiveValue::isRelativeUnit(
            primitiveValue.typeWithCalcResolved())) {
      // Instead of the actual zoom, use 1 to avoid potential rounding errors
      Length length = primitiveValue.convertToLength(
          state.cssToLengthConversionData().copyWithAdjustedZoom(1));
      return *CSSPrimitiveValue::create(length, 1);
    }
  }
  return value;
}

}  // namespace blink
