// Copyright 2014 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/cssom/computed_style.h"

#include <memory>
#include <utility>
#include <vector>

#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/cssom/absolute_url_value.h"
#include "cobalt/cssom/calc_value.h"
#include "cobalt/cssom/cobalt_ui_nav_focus_transform_function.h"
#include "cobalt/cssom/cobalt_ui_nav_spotlight_transform_function.h"
#include "cobalt/cssom/css_computed_style_data.h"
#include "cobalt/cssom/css_computed_style_declaration.h"
#include "cobalt/cssom/font_weight_value.h"
#include "cobalt/cssom/keyword_value.h"
#include "cobalt/cssom/length_value.h"
#include "cobalt/cssom/linear_gradient_value.h"
#include "cobalt/cssom/matrix_function.h"
#include "cobalt/cssom/number_value.h"
#include "cobalt/cssom/percentage_value.h"
#include "cobalt/cssom/property_list_value.h"
#include "cobalt/cssom/property_value_visitor.h"
#include "cobalt/cssom/radial_gradient_value.h"
#include "cobalt/cssom/rotate_function.h"
#include "cobalt/cssom/scale_function.h"
#include "cobalt/cssom/shadow_value.h"
#include "cobalt/cssom/transform_function.h"
#include "cobalt/cssom/transform_function_list_value.h"
#include "cobalt/cssom/transform_function_visitor.h"
#include "cobalt/cssom/translate_function.h"
#include "cobalt/cssom/url_value.h"

namespace cobalt {
namespace cssom {

namespace {

scoped_refptr<LengthValue> ProvideAbsoluteLength(
    const scoped_refptr<LengthValue>& specified_length,
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size,
    const math::Size& viewport_size) {
  switch (specified_length->unit()) {
    // "px" is an absolute unit.
    //   https://www.w3.org/TR/css3-values/#absolute-lengths
    case kPixelsUnit:
      return scoped_refptr<LengthValue>(specified_length);

    // "em" equals to the computed value of the "font-size" property of
    // the element on which it is used.
    //   https://www.w3.org/TR/css3-values/#font-relative-lengths
    case kFontSizesAkaEmUnit: {
      DCHECK_EQ(kPixelsUnit, computed_font_size->unit());

      return new LengthValue(
          computed_font_size->value() * specified_length->value(), kPixelsUnit);
    }

    // "rem" equals to the computed value of font-size on the root element.
    //   https://www.w3.org/TR/css3-values/#font-relative-lengths
    case kRootElementFontSizesAkaRemUnit: {
      DCHECK_EQ(kPixelsUnit, root_computed_font_size->unit());

      return new LengthValue(
          root_computed_font_size->value() * specified_length->value(),
          kPixelsUnit);
    }

    // "vw" equal to 1% of the width of the initial containing block.
    //   https://www.w3.org/TR/css3-values/#viewport-relative-lengths
    case kViewportWidthPercentsAkaVwUnit: {
      return new LengthValue(
          viewport_size.width() * specified_length->value() / 100.0f,
          kPixelsUnit);
    }

    // "vh" equal to 1% of the height of the initial containing block.
    //   https://www.w3.org/TR/css3-values/#viewport-relative-lengths
    case kViewportHeightPercentsAkaVhUnit: {
      return new LengthValue(
          viewport_size.height() * specified_length->value() / 100.0f,
          kPixelsUnit);
    }
  }
  NOTREACHED();
  return NULL;
}

// For values that can be either lengths or percentages, this function will
// return a value that, if the original value was a length, is now
// absolutized.
scoped_refptr<PropertyValue> ProvideAbsoluteLengthIfNonNullLength(
    const scoped_refptr<PropertyValue>& specified_value,
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size,
    const math::Size& viewport_size) {
  if (!specified_value) {
    return specified_value;
  }

  if (specified_value->GetTypeId() == base::GetTypeId<LengthValue>()) {
    LengthValue* value_as_length =
        base::polymorphic_downcast<LengthValue*>(specified_value.get());

    return ProvideAbsoluteLength(value_as_length, computed_font_size,
                                 root_computed_font_size, viewport_size);
  } else {
    return specified_value;
  }
}

// Applices ProvideAbsoluteLengthIfNonNullLength() for every item in a
// PropertyValueList.
scoped_refptr<PropertyListValue> ProvideAbsoluteLengthsForNonNullLengthsInList(
    const scoped_refptr<PropertyListValue>& specified_value,
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size,
    const math::Size& viewport_size) {
  std::unique_ptr<PropertyListValue::Builder> builder(
      new PropertyListValue::Builder());
  builder->reserve(specified_value->value().size());

  for (PropertyListValue::Builder::const_iterator iter =
           specified_value->value().begin();
       iter != specified_value->value().end(); ++iter) {
    builder->push_back(ProvideAbsoluteLengthIfNonNullLength(
        *iter, computed_font_size, root_computed_font_size, viewport_size));
  }

  return new PropertyListValue(std::move(builder));
}

// Computed value: absolute length;
//                 '0' if the border style is 'none' or 'hidden'.
//   https://www.w3.org/TR/css3-background/#border-width
class ComputedBorderWidthProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedBorderWidthProvider(const LengthValue* computed_font_size,
                              const LengthValue* root_computed_font_size,
                              const math::Size& viewport_size,
                              const PropertyValue* border_style);

  void VisitLength(LengthValue* length) override;

  const scoped_refptr<PropertyValue>& computed_border_width() const {
    return computed_border_width_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;
  const PropertyValue* border_style_;

  scoped_refptr<PropertyValue> computed_border_width_;

  DISALLOW_COPY_AND_ASSIGN(ComputedBorderWidthProvider);
};

ComputedBorderWidthProvider::ComputedBorderWidthProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size,
    const PropertyValue* border_style)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size),
      border_style_(border_style) {}

void ComputedBorderWidthProvider::VisitLength(LengthValue* specified_length) {
  if (border_style_ == KeywordValue::GetNone().get() ||
      border_style_ == KeywordValue::GetHidden().get()) {
    computed_border_width_ = new LengthValue(0, kPixelsUnit);
  } else {
    DCHECK_EQ(border_style_, KeywordValue::GetSolid().get());
    computed_border_width_ =
        ProvideAbsoluteLength(specified_length, computed_font_size_,
                              root_computed_font_size_, viewport_size_);
  }
}

// Computed value: numeric weight value.
//   https://www.w3.org/TR/css3-fonts/#font-weight-prop
class ComputedFontWeightProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedFontWeightProvider() {}

  void VisitFontWeight(FontWeightValue* weight) override;

  const scoped_refptr<FontWeightValue>& computed_font_weight() const {
    return computed_font_weight_;
  }

 private:
  scoped_refptr<FontWeightValue> computed_font_weight_;

  DISALLOW_COPY_AND_ASSIGN(ComputedFontWeightProvider);
};

// TODO: Support bolder and lighter. Match the weight with font face.
// Quite often there are only a few weights available for a particular font
// family. When a weight is specified for which no face exists, a face with a
// nearby weight is used.
//   https://www.w3.org/TR/css3-fonts/#font-matching-algorithm
void ComputedFontWeightProvider::VisitFontWeight(
    FontWeightValue* specified_weight) {
  computed_font_weight_ = specified_weight;
}

// Computed value: absolute length.
//   https://www.w3.org/TR/css3-fonts/#font-size-prop
class ComputedFontSizeProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedFontSizeProvider(const LengthValue* parent_computed_font_size,
                           const LengthValue* root_computed_font_size,
                           const math::Size& viewport_size);

  void VisitLength(LengthValue* length) override;
  void VisitPercentage(PercentageValue* percentage) override;

  const scoped_refptr<LengthValue>& computed_font_size() const {
    return computed_font_size_;
  }

 private:
  const LengthValue* parent_computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<LengthValue> computed_font_size_;

  DISALLOW_COPY_AND_ASSIGN(ComputedFontSizeProvider);
};

ComputedFontSizeProvider::ComputedFontSizeProvider(
    const LengthValue* parent_computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : parent_computed_font_size_(parent_computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedFontSizeProvider::VisitLength(LengthValue* specified_length) {
  // "em" on "font-size" is calculated relatively to the inherited value
  // of "font-size".
  //   https://www.w3.org/TR/css3-values/#font-relative-lengths
  computed_font_size_ =
      ProvideAbsoluteLength(specified_length, parent_computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedFontSizeProvider::VisitPercentage(
    PercentageValue* specified_percentage) {
  // A percentage value specifies an absolute font size relative to the parent
  // element's fonts size.
  //   https://www.w3.org/TR/css3-fonts/#percentage-size-value
  computed_font_size_ = new LengthValue(
      parent_computed_font_size_->value() * specified_percentage->value(),
      kPixelsUnit);
}

// Computed value: for length and percentage the absolute value;
//                 otherwise as specified.
//   https://www.w3.org/TR/CSS21/visudet.html#line-height
class ComputedLineHeightProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedLineHeightProvider(const LengthValue* computed_font_size,
                             const LengthValue* root_computed_font_size,
                             const math::Size& viewport_size);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitLength(LengthValue* length) override;
  void VisitNumber(NumberValue* number) override;
  void VisitPercentage(PercentageValue* percentage) override;

  const scoped_refptr<PropertyValue>& computed_line_height() const {
    return computed_line_height_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_line_height_;

  DISALLOW_COPY_AND_ASSIGN(ComputedLineHeightProvider);
};

ComputedLineHeightProvider::ComputedLineHeightProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedLineHeightProvider::VisitLength(LengthValue* specified_length) {
  computed_line_height_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedLineHeightProvider::VisitNumber(NumberValue* specified_number) {
  // The computed value is the same as the specified value.
  //   https://www.w3.org/TR/CSS2/visudet.html#line-height
  computed_line_height_ = specified_number;
}

void ComputedLineHeightProvider::VisitPercentage(PercentageValue* percentage) {
  // The computed value of the property is this percentage multiplied by the
  // element's computed font size. Negative values are illegal.
  //   https://www.w3.org/TR/CSS21/visudet.html#line-height
  computed_line_height_ = new LengthValue(
      computed_font_size_->value() * percentage->value(), kPixelsUnit);
}

void ComputedLineHeightProvider::VisitKeyword(KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kNormal:
      computed_line_height_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

// Computed value: the percentage as specified or the absolute length.
//   https://www.w3.org/TR/CSS21/box.html#margin-properties
//   https://www.w3.org/TR/CSS21/box.html#padding-properties
class ComputedMarginOrPaddingEdgeProvider
    : public NotReachedPropertyValueVisitor {
 public:
  ComputedMarginOrPaddingEdgeProvider(
      const LengthValue* computed_font_size,
      const LengthValue* root_computed_font_size,
      const math::Size& viewport_size);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitLength(LengthValue* length) override;
  void VisitPercentage(PercentageValue* percentage) override;

  const scoped_refptr<PropertyValue>& computed_margin_or_padding_edge() const {
    return computed_margin_or_padding_edge_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_margin_or_padding_edge_;

  DISALLOW_COPY_AND_ASSIGN(ComputedMarginOrPaddingEdgeProvider);
};

ComputedMarginOrPaddingEdgeProvider::ComputedMarginOrPaddingEdgeProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedMarginOrPaddingEdgeProvider::VisitKeyword(KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kAuto:
      computed_margin_or_padding_edge_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

void ComputedMarginOrPaddingEdgeProvider::VisitLength(
    LengthValue* specified_length) {
  computed_margin_or_padding_edge_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedMarginOrPaddingEdgeProvider::VisitPercentage(
    PercentageValue* percentage) {
  computed_margin_or_padding_edge_ = percentage;
}

class ComputedPositionOffsetProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedPositionOffsetProvider(const LengthValue* computed_font_size,
                                 const LengthValue* root_computed_font_size,
                                 const math::Size& viewport_size);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitLength(LengthValue* length) override;
  void VisitPercentage(PercentageValue* percentage) override;

  const scoped_refptr<PropertyValue>& computed_position_offset() const {
    return computed_position_offset_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_position_offset_;

  DISALLOW_COPY_AND_ASSIGN(ComputedPositionOffsetProvider);
};

void ComputedPositionOffsetProvider::VisitLength(
    LengthValue* specified_length) {
  computed_position_offset_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedPositionOffsetProvider::VisitKeyword(KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kAuto:
      computed_position_offset_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

void ComputedPositionOffsetProvider::VisitPercentage(
    PercentageValue* percentage) {
  computed_position_offset_ = percentage;
}

ComputedPositionOffsetProvider::ComputedPositionOffsetProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

// Computed value: the percentage or "auto" or the absolute length.
//   https://www.w3.org/TR/CSS21/visudet.html#the-height-property
class ComputedHeightProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedHeightProvider(const PropertyValue* parent_computed_height,
                         const PropertyValue* parent_computed_top,
                         const PropertyValue* parent_computed_bottom,
                         const LengthValue* computed_font_size,
                         const LengthValue* root_computed_font_size,
                         const math::Size& viewport_size, bool out_of_flow);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitLength(LengthValue* length) override;
  void VisitPercentage(PercentageValue* percentage) override;

  const scoped_refptr<PropertyValue>& computed_height() const {
    return computed_height_;
  }

 private:
  const PropertyValue* parent_computed_height_;
  const PropertyValue* parent_computed_top_;
  const PropertyValue* parent_computed_bottom_;
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;
  bool out_of_flow_;

  scoped_refptr<PropertyValue> computed_height_;

  DISALLOW_COPY_AND_ASSIGN(ComputedHeightProvider);
};

ComputedHeightProvider::ComputedHeightProvider(
    const PropertyValue* parent_computed_height,
    const PropertyValue* parent_computed_top,
    const PropertyValue* parent_computed_bottom,
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size,
    bool out_of_flow)
    : parent_computed_height_(parent_computed_height),
      parent_computed_top_(parent_computed_top),
      parent_computed_bottom_(parent_computed_bottom),
      computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size),
      out_of_flow_(out_of_flow) {}

void ComputedHeightProvider::VisitLength(LengthValue* specified_length) {
  computed_height_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedHeightProvider::VisitKeyword(KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kAuto:
      computed_height_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

void ComputedHeightProvider::VisitPercentage(PercentageValue* percentage) {
  const scoped_refptr<PropertyValue>& auto_value = KeywordValue::GetAuto();

  // If the height of the containing block is not specified explicitly
  // (i.e., it depends on content height), and this element is not absolutely
  // positioned, the value computes to "auto".
  //   https://www.w3.org/TR/CSS21/visudet.html#the-height-property
  computed_height_ = (parent_computed_height_ == auto_value &&
                      (parent_computed_top_ == auto_value ||
                       parent_computed_bottom_ == auto_value) &&
                      !out_of_flow_)
                         ? auto_value
                         : percentage;
}

// Computed value: the percentage or "auto" or the absolute length.
//   https://www.w3.org/TR/CSS2/visudet.html#propdef-max-height
class ComputedMaxHeightProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedMaxHeightProvider(const PropertyValue* parent_computed_max_height,
                            const LengthValue* computed_font_size,
                            const LengthValue* root_computed_font_size,
                            const math::Size& viewport_size, bool out_of_flow);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitLength(LengthValue* length) override;
  void VisitPercentage(PercentageValue* percentage) override;

  const scoped_refptr<PropertyValue>& computed_max_height() const {
    return computed_max_height_;
  }

 private:
  const PropertyValue* parent_computed_max_height_;
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;
  bool out_of_flow_;

  scoped_refptr<PropertyValue> computed_max_height_;

  DISALLOW_COPY_AND_ASSIGN(ComputedMaxHeightProvider);
};

ComputedMaxHeightProvider::ComputedMaxHeightProvider(
    const PropertyValue* parent_computed_max_height,
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size,
    bool out_of_flow)
    : parent_computed_max_height_(parent_computed_max_height),
      computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size),
      out_of_flow_(out_of_flow) {}

void ComputedMaxHeightProvider::VisitLength(LengthValue* specified_length) {
  computed_max_height_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedMaxHeightProvider::VisitKeyword(KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kAuto:
    case KeywordValue::kNone:
      computed_max_height_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

void ComputedMaxHeightProvider::VisitPercentage(PercentageValue* percentage) {
  const scoped_refptr<PropertyValue>& auto_value = KeywordValue::GetAuto();
  const scoped_refptr<PropertyValue>& none_value = KeywordValue::GetNone();

  // If the max_height of the containing block is not specified explicitly
  // (i.e., it depends on content max_height), and this element is not
  // absolutely positioned, the percentage value is treated as 'none'.
  //   https://www.w3.org/TR/CSS2/visudet.html#propdef-max-height
  computed_max_height_ =
      (parent_computed_max_height_ == auto_value && !out_of_flow_) ? none_value
                                                                   : percentage;
}

// Computed value: the percentage or "auto" or the absolute length.
//   https://www.w3.org/TR/CSS2/visudet.html#propdef-min-height
class ComputedMinHeightProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedMinHeightProvider(const PropertyValue* parent_computed_height,
                            const LengthValue* computed_font_size,
                            const LengthValue* root_computed_font_size,
                            const math::Size& viewport_size, bool out_of_flow);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitLength(LengthValue* length) override;
  void VisitPercentage(PercentageValue* percentage) override;

  const scoped_refptr<PropertyValue>& computed_min_height() const {
    return computed_min_height_;
  }

 private:
  const PropertyValue* parent_computed_height_;
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;
  bool out_of_flow_;

  scoped_refptr<PropertyValue> computed_min_height_;

  DISALLOW_COPY_AND_ASSIGN(ComputedMinHeightProvider);
};

ComputedMinHeightProvider::ComputedMinHeightProvider(
    const PropertyValue* parent_computed_height,
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size,
    bool out_of_flow)
    : parent_computed_height_(parent_computed_height),
      computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size),
      out_of_flow_(out_of_flow) {}

void ComputedMinHeightProvider::VisitLength(LengthValue* specified_length) {
  computed_min_height_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedMinHeightProvider::VisitKeyword(KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kAuto:
      computed_min_height_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

void ComputedMinHeightProvider::VisitPercentage(PercentageValue* percentage) {
  const scoped_refptr<PropertyValue>& auto_value = KeywordValue::GetAuto();

  // If the height of the containing block is not specified explicitly
  // (i.e., it depends on content height), and this element is not
  // absolutely positioned, the percentage value is treated as '0'.
  //   https://www.w3.org/TR/CSS2/visudet.html#propdef-min-height
  if (parent_computed_height_ == auto_value && !out_of_flow_) {
    computed_min_height_ = new LengthValue(0, kPixelsUnit);
  } else {
    computed_min_height_ = percentage;
  }
}

// Computed value: the percentage or "auto" as specified or the absolute length.
//   https://www.w3.org/TR/CSS21/visudet.html#the-width-property
class ComputedWidthValueProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedWidthValueProvider(const LengthValue* computed_font_size,
                             const LengthValue* root_computed_font_size,
                             const math::Size& viewport_size);

  void VisitLength(LengthValue* length) override;
  void VisitPercentage(PercentageValue* percentage) override;

  const scoped_refptr<PropertyValue>& computed_value() const {
    return computed_value_;
  }

 protected:
  scoped_refptr<PropertyValue> computed_value_;

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  DISALLOW_COPY_AND_ASSIGN(ComputedWidthValueProvider);
};

ComputedWidthValueProvider::ComputedWidthValueProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedWidthValueProvider::VisitLength(LengthValue* specified_length) {
  computed_value_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedWidthValueProvider::VisitPercentage(PercentageValue* percentage) {
  computed_value_ = percentage;
}

// Computed value: For auto the width depends on the values of other properties.
//  https://www.w3.org/TR/CSS21/visudet.html#the-width-property
class ComputedWidthProvider : public ComputedWidthValueProvider {
 public:
  ComputedWidthProvider(const LengthValue* computed_font_size,
                        const LengthValue* root_computed_font_size,
                        const math::Size& viewport_size)
      : ComputedWidthValueProvider(computed_font_size, root_computed_font_size,
                                   viewport_size) {}

  void VisitKeyword(KeywordValue* keyword) {
    switch (keyword->value()) {
      case KeywordValue::kAuto:
        computed_value_ = keyword;
        break;

      default:
        NOTREACHED();
    }
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ComputedWidthProvider);
};

// Computed value: For all values other than auto and content, flex-basis is
// resolved the same way as width.
//  https://www.w3.org/TR/css-flexbox-1/#flex-basis-property
class ComputedFlexBasisProvider : public ComputedWidthValueProvider {
 public:
  ComputedFlexBasisProvider(const LengthValue* computed_font_size,
                            const LengthValue* root_computed_font_size,
                            const math::Size& viewport_size)
      : ComputedWidthValueProvider(computed_font_size, root_computed_font_size,
                                   viewport_size) {}

  void VisitKeyword(KeywordValue* keyword) {
    switch (keyword->value()) {
      case KeywordValue::kAuto:
      case KeywordValue::kContent:
        computed_value_ = keyword;
        break;

      default:
        NOTREACHED();
    }
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(ComputedFlexBasisProvider);
};

// Computed value: the percentage or "auto" as specified or the absolute length.
//   https://www.w3.org/TR/CSS2/visudet.html#min-max-widths
class ComputedMinMaxWidthProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedMinMaxWidthProvider(PropertyValue* parent_computed_width,
                              const LengthValue* computed_font_size,
                              const LengthValue* root_computed_font_size,
                              const math::Size& viewport_size);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitLength(LengthValue* length) override;
  void VisitPercentage(PercentageValue* percentage) override;

  const scoped_refptr<PropertyValue>& computed_min_max_width() const {
    return computed_min_max_width_;
  }

 private:
  PropertyValue* parent_computed_width_;
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_min_max_width_;

  DISALLOW_COPY_AND_ASSIGN(ComputedMinMaxWidthProvider);
};

ComputedMinMaxWidthProvider::ComputedMinMaxWidthProvider(
    PropertyValue* parent_computed_width, const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : parent_computed_width_(parent_computed_width),
      computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedMinMaxWidthProvider::VisitLength(LengthValue* specified_length) {
  computed_min_max_width_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedMinMaxWidthProvider::VisitKeyword(KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kAuto:
    case KeywordValue::kNone:
      computed_min_max_width_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

class ComputedLengthIsNegativeProvider : public DefaultingPropertyValueVisitor {
 public:
  ComputedLengthIsNegativeProvider() : computed_length_is_negative_(false) {}

  void VisitLength(LengthValue* length_value) override {
    switch (length_value->unit()) {
      case kPixelsUnit:
      case kFontSizesAkaEmUnit:
      case kRootElementFontSizesAkaRemUnit:
      case kViewportWidthPercentsAkaVwUnit:
      case kViewportHeightPercentsAkaVhUnit:
        computed_length_is_negative_ = length_value->value() < 0;
        break;
    }
  }

  void VisitDefault(PropertyValue* property_value) override {}

  bool computed_length_is_negative() { return computed_length_is_negative_; }

 private:
  bool computed_length_is_negative_;
};

void ComputedMinMaxWidthProvider::VisitPercentage(PercentageValue* percentage) {
  ComputedLengthIsNegativeProvider computed_length_is_negative_provider;
  parent_computed_width_->Accept(&computed_length_is_negative_provider);
  // If the containing block's width is negative, the used value is zero.
  //   https://www.w3.org/TR/CSS2/visudet.html#min-max-widths
  if (computed_length_is_negative_provider.computed_length_is_negative()) {
    computed_min_max_width_ = new LengthValue(0, kPixelsUnit);
  } else {
    computed_min_max_width_ = percentage;
  }
}

namespace {

// Helper class for |ComputedBackgroundPositionProvider| and
// |ComputedTransformOriginProvider| to resolve the computed value of position
// part.
//   https://www.w3.org/TR/css3-background/#the-background-position
//   https://www.w3.org/TR/css3-transforms/#propdef-transform-origin
class ComputedPositionHelper {
 public:
  ComputedPositionHelper(const LengthValue* computed_font_size,
                         const LengthValue* root_computed_font_size,
                         const math::Size& viewport_size);

  // Forwards the call on to the appropriate method depending on the number
  // of parameters in |input_position_builder|.
  void ComputePosition(const PropertyListValue::Builder& input_position_builder,
                       PropertyListValue::Builder* output_position_builder);

  // Only resolve the first value of |input_position_builder|, other than the
  // first value would be ignored.
  void ComputeOneValuePosition(
      const PropertyListValue::Builder& input_position_builder,
      PropertyListValue::Builder* output_position_builder);

  // Only resolve the first two values of |input_position_builder|, other than
  // the first two values would be ignored.
  void ComputeTwoValuesPosition(
      const PropertyListValue::Builder& input_position_builder,
      PropertyListValue::Builder* output_position_builder);

  // Only resolve three or four values of |input_position_builder|.
  void ComputeThreeOrFourValuesPosition(
      const PropertyListValue::Builder& input_position_builder,
      PropertyListValue::Builder* output_position_builder);

 private:
  enum Direction {
    kHorizontal,
    kVertical,
    kCenter,
    kNone,
  };

  struct OriginInfo {
    OriginInfo(float origin_as_percentage, int offset_multiplier,
               Direction direction)
        : origin_as_percentage(origin_as_percentage),
          offset_multiplier(offset_multiplier),
          direction(direction) {}

    float origin_as_percentage;
    int offset_multiplier;
    Direction direction;
  };

  const OriginInfo ConvertToOriginInfo(
      const scoped_refptr<PropertyValue>& keyword) const;

  scoped_refptr<CalcValue> ProvideCalcValueFromOriginAndOffset(
      OriginInfo* origin_info, const scoped_refptr<PropertyValue>& offset);

  void FillPositionBuilderFromOriginAndOffset(
      const scoped_refptr<PropertyValue>& origin,
      const scoped_refptr<PropertyValue>& offset,
      PropertyListValue::Builder* position_builder);

  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  DISALLOW_COPY_AND_ASSIGN(ComputedPositionHelper);
};

ComputedPositionHelper::ComputedPositionHelper(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedPositionHelper::ComputePosition(
    const PropertyListValue::Builder& input_position_builder,
    PropertyListValue::Builder* output_position_builder) {
  switch (input_position_builder.size()) {
    case 1:
      ComputeOneValuePosition(input_position_builder, output_position_builder);
      break;
    case 2:
      ComputeTwoValuesPosition(input_position_builder, output_position_builder);
      break;
    case 3:  // fall-through
    case 4:
      ComputeThreeOrFourValuesPosition(input_position_builder,
                                       output_position_builder);
      break;
  }
}

// If only one value is specified, the second value is assumed to be center.
void ComputedPositionHelper::ComputeOneValuePosition(
    const PropertyListValue::Builder& input_position_builder,
    PropertyListValue::Builder* output_position_builder) {
  DCHECK_GE(input_position_builder.size(), 1u);

  PropertyListValue::Builder position_builder;
  position_builder.push_back(input_position_builder[0]);
  position_builder.push_back(KeywordValue::GetCenter());

  ComputeTwoValuesPosition(position_builder, output_position_builder);
}

// If two position values are given, a length or percentage as the
// first value represents the horizontal position (or offset) and a length or
// percentage as the second value represents the vertical position (or offset).
void ComputedPositionHelper::ComputeTwoValuesPosition(
    const PropertyListValue::Builder& input_position_builder,
    PropertyListValue::Builder* output_position_builder) {
  DCHECK_GE(input_position_builder.size(), 2u);

  for (size_t i = 0; i < 2; ++i) {
    scoped_refptr<PropertyValue> current_value = input_position_builder[i];

    if (current_value->GetTypeId() == base::GetTypeId<CalcValue>()) {
      // If it is already a CalcValue, nothing needs to be done.
      (*output_position_builder)[i] = current_value;
    } else if (current_value->GetTypeId() == base::GetTypeId<KeywordValue>()) {
      FillPositionBuilderFromOriginAndOffset(current_value, NULL,
                                             output_position_builder);
    } else {
      OriginInfo default_origin = OriginInfo(0.0f, 1, kNone);
      (*output_position_builder)[i] =
          ProvideCalcValueFromOriginAndOffset(&default_origin, current_value);
    }
  }
}

// If three values are given, then there are two cases:
// 1. <KeywordValue Length/Percentage KeywordValue>
// 2. <KeywordValue KeywordValue Length/Percentage>
// If four values are given, then each <percentage> or <length> represents
// an offset and must be preceded by a keyword, which specifies from which
// edge the offset is given. Keyword cannot be 'center'. The pattern is
// <KeywordValue Length/Percentage KeywordValue Length/Percentage>
void ComputedPositionHelper::ComputeThreeOrFourValuesPosition(
    const PropertyListValue::Builder& input_position_builder,
    PropertyListValue::Builder* output_position_builder) {
  DCHECK_GT(input_position_builder.size(), 2u);
  DCHECK_LE(input_position_builder.size(), 4u);

  for (size_t i = 0; i < input_position_builder.size(); ++i) {
    scoped_refptr<PropertyValue> previous_value =
        (i == 0) ? NULL : input_position_builder[i - 1];

    scoped_refptr<PropertyValue> current_value = input_position_builder[i];

    if (current_value->GetTypeId() == base::GetTypeId<KeywordValue>()) {
      FillPositionBuilderFromOriginAndOffset(current_value, NULL,
                                             output_position_builder);
    } else {
      DCHECK(previous_value);
      DCHECK(previous_value->GetTypeId() == base::GetTypeId<KeywordValue>());
      FillPositionBuilderFromOriginAndOffset(previous_value, current_value,
                                             output_position_builder);
    }
  }
}

// 1) 'top' computes to '0%' for the vertical position if one or two values are
//     given, otherwise specifies the top edge as the origin for the next
//     offset.
// 2) 'right' computes to '100%' for the horizontal position if one or two
//     values are given, otherwise specifies the right edge as the origin for
//     the next offset.
// 3) 'bottom' computes to '100%' for the vertical position if one or two values
//     are given, otherwise specifies the bottom edge as the origin for the
//     the next offset.
// 4) 'left' computes to '0%' for the horizontal position if one or two values
//     are given, otherwise specifies the left edge as the origin for the next
//     offset.
// 5) 'center' computes to '50%' (left 50%) for the horizontal position if
//     horizontal position is not specified, or '50%' (right 50%) for the
//     vertical position is not specified.
const ComputedPositionHelper::OriginInfo
ComputedPositionHelper::ConvertToOriginInfo(
    const scoped_refptr<PropertyValue>& keyword) const {
  DCHECK(keyword->GetTypeId() == base::GetTypeId<KeywordValue>());

  if (keyword == KeywordValue::GetLeft()) {
    return OriginInfo(0.0f, 1, kHorizontal);
  } else if (keyword == KeywordValue::GetRight()) {
    return OriginInfo(1.0f, -1, kHorizontal);
  } else if (keyword == KeywordValue::GetTop()) {
    return OriginInfo(0.0f, 1, kVertical);
  } else if (keyword == KeywordValue::GetBottom()) {
    return OriginInfo(1.0f, -1, kVertical);
  } else {
    return OriginInfo(0.5f, 1, kCenter);
  }
}

// If the |offset| is specified, the |origin| specifies from which edge
// the offset is given. Otherwise, the |origin| indicates the corresponding
// percentage value to the upper left corner for the horizontal/vertical
// position. The horizontal and vertical values are stored as CalcValue in
// computed style. eg: (background-position: bottom 20px left 40%;) would be
// computed as Calc(0px, 40%), Calc(-20px, 100%)
scoped_refptr<CalcValue>
ComputedPositionHelper::ProvideCalcValueFromOriginAndOffset(
    OriginInfo* origin_info, const scoped_refptr<PropertyValue>& offset) {
  DCHECK(origin_info);

  if (!offset) {
    return new CalcValue(
        new PercentageValue(origin_info->origin_as_percentage));
  }

  scoped_refptr<LengthValue> length_value;
  scoped_refptr<PercentageValue> percentage_value;
  if (offset->GetTypeId() == base::GetTypeId<LengthValue>()) {
    scoped_refptr<LengthValue> length_provider = ProvideAbsoluteLength(
        base::polymorphic_downcast<LengthValue*>(offset.get()),
        computed_font_size_, root_computed_font_size_, viewport_size_);
    length_value = new LengthValue(
        origin_info->offset_multiplier * length_provider->value(),
        length_provider->unit());
    percentage_value = new PercentageValue(origin_info->origin_as_percentage);

    return new CalcValue(length_value, percentage_value);
  } else {
    DCHECK(offset->GetTypeId() == base::GetTypeId<PercentageValue>());
    PercentageValue* percentage =
        base::polymorphic_downcast<PercentageValue*>(offset.get());
    percentage_value = new PercentageValue(origin_info->origin_as_percentage +
                                           origin_info->offset_multiplier *
                                               percentage->value());

    return new CalcValue(percentage_value);
  }
}

void ComputedPositionHelper::FillPositionBuilderFromOriginAndOffset(
    const scoped_refptr<PropertyValue>& origin,
    const scoped_refptr<PropertyValue>& offset,
    PropertyListValue::Builder* output_position_builder) {
  DCHECK(origin->GetTypeId() == base::GetTypeId<KeywordValue>());

  OriginInfo origin_info = ConvertToOriginInfo(origin);
  switch (origin_info.direction) {
    case kHorizontal: {
      (*output_position_builder)[0] =
          ProvideCalcValueFromOriginAndOffset(&origin_info, offset);
      break;
    }
    case kVertical: {
      (*output_position_builder)[1] =
          ProvideCalcValueFromOriginAndOffset(&origin_info, offset);
      break;
    }
    case kCenter: {
      if (!(*output_position_builder)[0]) {
        (*output_position_builder)[0] =
            ProvideCalcValueFromOriginAndOffset(&origin_info, offset);
      }
      if (!(*output_position_builder)[1]) {
        (*output_position_builder)[1] =
            ProvideCalcValueFromOriginAndOffset(&origin_info, offset);
      }
      break;
    }
    case kNone:  // fall-through
      NOTREACHED();
      break;
  }
}

}  // namespace

// Absolutizes the value of "background-image" property.
// Computed value: as specified, but with URIs made absolute.
//   https://www.w3.org/TR/css3-background/#the-background-image
class ComputedBackgroundImageSingleLayerProvider
    : public NotReachedPropertyValueVisitor {
 public:
  ComputedBackgroundImageSingleLayerProvider(
      const GURL& base_url, const LengthValue* computed_font_size,
      const LengthValue* root_computed_font_size,
      const math::Size& viewport_size)
      : base_url_(base_url),
        computed_font_size_(computed_font_size),
        root_computed_font_size_(root_computed_font_size),
        viewport_size_(viewport_size) {}

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitLinearGradient(LinearGradientValue* linear_gradient_value) override;
  void VisitRadialGradient(RadialGradientValue* radial_gradient_value) override;
  void VisitURL(URLValue* url_value) override;

  const scoped_refptr<PropertyValue>& computed_background_image() const {
    return computed_background_image_;
  }

 private:
  const GURL base_url_;
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_background_image_;
};

void ComputedBackgroundImageSingleLayerProvider::VisitKeyword(
    KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kNone:
      computed_background_image_ = keyword;
      break;

    default:
      NOTREACHED();
      break;
  }
}

namespace {
ColorStopList ComputeColorStopList(const ColorStopList& color_stops,
                                   const LengthValue* computed_font_size,
                                   const LengthValue* root_computed_font_size,
                                   const math::Size& viewport_size) {
  ColorStopList computed_color_stops;
  computed_color_stops.reserve(color_stops.size());

  for (ColorStopList::const_iterator iter = color_stops.begin();
       iter != color_stops.end(); ++iter) {
    const ColorStop& color_stop = **iter;

    computed_color_stops.emplace_back(new ColorStop(
        color_stop.rgba(), ProvideAbsoluteLengthIfNonNullLength(
                               color_stop.position(), computed_font_size,
                               root_computed_font_size, viewport_size)));
  }

  return computed_color_stops;
}
}  // namespace

void ComputedBackgroundImageSingleLayerProvider::VisitLinearGradient(
    LinearGradientValue* linear_gradient_value) {
  // We must walk through the list of color stop positions and absolutize the
  // any length values.
  ColorStopList computed_color_stops = ComputeColorStopList(
      linear_gradient_value->color_stop_list(), computed_font_size_,
      root_computed_font_size_, viewport_size_);

  if (linear_gradient_value->angle_in_radians()) {
    computed_background_image_ =
        new LinearGradientValue(*linear_gradient_value->angle_in_radians(),
                                std::move(computed_color_stops));
  } else {
    computed_background_image_ =
        new LinearGradientValue(*linear_gradient_value->side_or_corner(),
                                std::move(computed_color_stops));
  }
}

namespace {
scoped_refptr<PropertyListValue> CalculateComputedRadialGradientPosition(
    const scoped_refptr<PropertyListValue>& specified_position,
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size,
    const math::Size& viewport_size) {
  if (!specified_position) {
    // If no position is specified, we default to 'center'.
    std::unique_ptr<PropertyListValue::Builder> builder(
        new PropertyListValue::Builder(2, new PercentageValue(0.5f)));
    return new PropertyListValue(std::move(builder));
  }

  size_t size = specified_position->value().size();
  DCHECK_GE(size, 1u);
  DCHECK_LE(size, 4u);

  ComputedPositionHelper position_helper(
      computed_font_size, root_computed_font_size, viewport_size);
  std::unique_ptr<PropertyListValue::Builder> computed_position_builder(
      new PropertyListValue::Builder(2, scoped_refptr<PropertyValue>()));
  position_helper.ComputePosition(specified_position->value(),
                                  computed_position_builder.get());

  return new PropertyListValue(std::move(computed_position_builder));
}
}  // namespace

void ComputedBackgroundImageSingleLayerProvider::VisitRadialGradient(
    RadialGradientValue* radial_gradient_value) {
  // We must walk through the list of color stop positions and absolutize the
  // any length values.
  ColorStopList computed_color_stops = ComputeColorStopList(
      radial_gradient_value->color_stop_list(), computed_font_size_,
      root_computed_font_size_, viewport_size_);

  // The center of the gradient must be absolutized if it is a length.
  scoped_refptr<PropertyListValue> computed_position =
      CalculateComputedRadialGradientPosition(
          radial_gradient_value->position(), computed_font_size_,
          root_computed_font_size_, viewport_size_);

  // If the radial gradient specifies size values, they must also be absolutized
  // if they are lengths.
  if (radial_gradient_value->size_value()) {
    computed_background_image_ = new RadialGradientValue(
        radial_gradient_value->shape(),
        ProvideAbsoluteLengthsForNonNullLengthsInList(
            radial_gradient_value->size_value(), computed_font_size_,
            root_computed_font_size_, viewport_size_),
        computed_position, std::move(computed_color_stops));
  } else {
    computed_background_image_ = new RadialGradientValue(
        radial_gradient_value->shape(), *radial_gradient_value->size_keyword(),
        computed_position, std::move(computed_color_stops));
  }
}

void ComputedBackgroundImageSingleLayerProvider::VisitURL(URLValue* url_value) {
  if (url_value->value().empty()) {
    // No need to convert URLValue into AbsoluteURLValue.
    computed_background_image_ = KeywordValue::GetNone();
    return;
  }

  GURL absolute_url;
  if (url_value->is_absolute()) {
    absolute_url = GURL(url_value->value());
  } else {
    absolute_url = url_value->Resolve(base_url_);
  }

  if (!absolute_url.is_valid()) {
    DLOG(WARNING) << "Invalid url: " << absolute_url.spec();
    // No further process is needed if the url is invalid.
    computed_background_image_ = KeywordValue::GetNone();
    return;
  }

  computed_background_image_ = new AbsoluteURLValue(absolute_url);
}

class ComputedBackgroundImageProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedBackgroundImageProvider(const GURL& base_url,
                                  const LengthValue* computed_font_size,
                                  const LengthValue* root_computed_font_size,
                                  const math::Size& viewport_size)
      : base_url_(base_url),
        computed_font_size_(computed_font_size),
        root_computed_font_size_(root_computed_font_size),
        viewport_size_(viewport_size) {}

  void VisitPropertyList(PropertyListValue* property_list_value) override;

  const scoped_refptr<PropertyValue>& computed_background_image() const {
    return computed_background_image_;
  }

 private:
  const GURL base_url_;
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_background_image_;
};

void ComputedBackgroundImageProvider::VisitPropertyList(
    PropertyListValue* property_list_value) {
  std::unique_ptr<PropertyListValue::Builder> builder(
      new PropertyListValue::Builder());
  builder->reserve(property_list_value->value().size());

  ComputedBackgroundImageSingleLayerProvider single_layer_provider(
      base_url_, computed_font_size_, root_computed_font_size_, viewport_size_);
  for (size_t i = 0; i < property_list_value->value().size(); ++i) {
    property_list_value->value()[i]->Accept(&single_layer_provider);
    scoped_refptr<PropertyValue> computed_background_image =
        single_layer_provider.computed_background_image();
    builder->push_back(computed_background_image);
  }

  computed_background_image_ = new PropertyListValue(std::move(builder));
}

class ComputedBackgroundSizeSingleValueProvider
    : public NotReachedPropertyValueVisitor {
 public:
  ComputedBackgroundSizeSingleValueProvider(
      const LengthValue* computed_font_size,
      const LengthValue* root_computed_font_size,
      const math::Size& viewport_size);

  void VisitLength(LengthValue* length) override;
  void VisitPercentage(PercentageValue* percentage) override;
  void VisitKeyword(KeywordValue* keyword) override;

  const scoped_refptr<PropertyValue>& computed_background_size() const {
    return computed_background_size_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_background_size_;

  DISALLOW_COPY_AND_ASSIGN(ComputedBackgroundSizeSingleValueProvider);
};

ComputedBackgroundSizeSingleValueProvider::
    ComputedBackgroundSizeSingleValueProvider(
        const LengthValue* computed_font_size,
        const LengthValue* root_computed_font_size,
        const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedBackgroundSizeSingleValueProvider::VisitLength(
    LengthValue* length) {
  computed_background_size_ = ProvideAbsoluteLength(
      length, computed_font_size_, root_computed_font_size_, viewport_size_);
}

void ComputedBackgroundSizeSingleValueProvider::VisitPercentage(
    PercentageValue* percentage) {
  computed_background_size_ = percentage;
}

void ComputedBackgroundSizeSingleValueProvider::VisitKeyword(
    KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kAuto:
    case KeywordValue::kContain:
    case KeywordValue::kCover:
      computed_background_size_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

// ComputedBackgroundPositionProvider provides a property list which has two
// CalcValue. Each of CalcValue has two parts <percentage> and <length>.
// <percentage> and <length> values here represent an offset of the top left
// corner of the background image from the top left corner of the background
// positioning area.
//   https://www.w3.org/TR/css3-background/#the-background-position
class ComputedBackgroundPositionProvider
    : public NotReachedPropertyValueVisitor {
 public:
  ComputedBackgroundPositionProvider(const LengthValue* computed_font_size,
                                     const LengthValue* root_computed_font_size,
                                     const math::Size& viewport_size);

  void VisitPropertyList(PropertyListValue* property_list_value) override;

  const scoped_refptr<PropertyValue>& computed_background_position() const {
    return computed_background_position_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_background_position_;

  DISALLOW_COPY_AND_ASSIGN(ComputedBackgroundPositionProvider);
};

ComputedBackgroundPositionProvider::ComputedBackgroundPositionProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedBackgroundPositionProvider::VisitPropertyList(
    PropertyListValue* property_list_value) {
  size_t size = property_list_value->value().size();
  DCHECK_GE(size, 1u);
  DCHECK_LE(size, 4u);

  ComputedPositionHelper position_helper(
      computed_font_size_, root_computed_font_size_, viewport_size_);
  std::unique_ptr<PropertyListValue::Builder> background_position_builder(
      new PropertyListValue::Builder(2, scoped_refptr<PropertyValue>()));

  position_helper.ComputePosition(property_list_value->value(),
                                  background_position_builder.get());

  computed_background_position_ =
      new PropertyListValue(std::move(background_position_builder));
}

class ComputedBackgroundSizeProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedBackgroundSizeProvider(const LengthValue* computed_font_size,
                                 const LengthValue* root_computed_font_size,
                                 const math::Size& viewport_size);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitPropertyList(PropertyListValue* property_list_value) override;

  const scoped_refptr<PropertyValue>& computed_background_size() const {
    return computed_background_size_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_background_size_;

  DISALLOW_COPY_AND_ASSIGN(ComputedBackgroundSizeProvider);
};

ComputedBackgroundSizeProvider::ComputedBackgroundSizeProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedBackgroundSizeProvider::VisitKeyword(KeywordValue* keyword) {
  computed_background_size_ = keyword;
}

void ComputedBackgroundSizeProvider::VisitPropertyList(
    PropertyListValue* property_list_value) {
  ComputedBackgroundSizeSingleValueProvider left_value_provider(
      computed_font_size_, root_computed_font_size_, viewport_size_);
  property_list_value->value()[0]->Accept(&left_value_provider);

  ComputedBackgroundSizeSingleValueProvider right_value_provider(
      computed_font_size_, root_computed_font_size_, viewport_size_);
  property_list_value->value()[1]->Accept(&right_value_provider);

  std::unique_ptr<PropertyListValue::Builder> builder(
      new PropertyListValue::Builder());
  builder->reserve(2);
  builder->push_back(left_value_provider.computed_background_size());
  builder->push_back(right_value_provider.computed_background_size());
  computed_background_size_ = new PropertyListValue(std::move(builder));
}

//    https://www.w3.org/TR/css3-background/#border-radius
class ComputedBorderRadiusProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedBorderRadiusProvider(const LengthValue* computed_font_size,
                               const LengthValue* root_computed_font_size,
                               const math::Size& viewport_size);

  void VisitLength(LengthValue* specified_length);
  void VisitPercentage(PercentageValue* percentage);

  const scoped_refptr<PropertyValue>& computed_border_radius() const {
    return computed_border_radius_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_border_radius_;

  DISALLOW_COPY_AND_ASSIGN(ComputedBorderRadiusProvider);
};

ComputedBorderRadiusProvider::ComputedBorderRadiusProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedBorderRadiusProvider::VisitLength(LengthValue* specified_length) {
  computed_border_radius_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

void ComputedBorderRadiusProvider::VisitPercentage(
    PercentageValue* percentage) {
  computed_border_radius_ = percentage;
}

// Computed value: any <length> made absolute; any specified color computed;
// otherwise as specified.
//   https://www.w3.org/TR/css3-background/#box-shadow
//   https://www.w3.org/TR/css-text-decor-3/#text-shadow-property
class ComputedShadowProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedShadowProvider(const LengthValue* computed_font_size,
                         const LengthValue* root_computed_font_size,
                         const math::Size& viewport_size,
                         const RGBAColorValue* computed_color);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitPropertyList(PropertyListValue* property_list_value) override;

  const scoped_refptr<PropertyValue>& computed_shadow() const {
    return computed_shadow_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;
  const RGBAColorValue* computed_color_;

  scoped_refptr<PropertyValue> computed_shadow_;

  DISALLOW_COPY_AND_ASSIGN(ComputedShadowProvider);
};

ComputedShadowProvider::ComputedShadowProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size,
    const RGBAColorValue* computed_color)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size),
      computed_color_(computed_color) {}

void ComputedShadowProvider::VisitKeyword(KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kNone:
      computed_shadow_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

void ComputedShadowProvider::VisitPropertyList(
    PropertyListValue* property_list_value) {
  std::unique_ptr<PropertyListValue::Builder> builder(
      new PropertyListValue::Builder());
  builder->reserve(property_list_value->value().size());

  for (size_t i = 0; i < property_list_value->value().size(); ++i) {
    ShadowValue* shadow_value = base::polymorphic_downcast<ShadowValue*>(
        property_list_value->value()[i].get());

    scoped_refptr<LengthValue> computed_lengths[ShadowValue::kMaxLengths];
    for (int j = 0; j < ShadowValue::kMaxLengths; ++j) {
      LengthValue* specified_length = shadow_value->lengths()[j].get();
      if (specified_length) {
        computed_lengths[j] =
            ProvideAbsoluteLength(specified_length, computed_font_size_,
                                  root_computed_font_size_, viewport_size_);
      }
    }

    scoped_refptr<RGBAColorValue> color = shadow_value->color();
    if (!color) {
      color = new RGBAColorValue(computed_color_->value());
    }

    builder->push_back(
        new ShadowValue(computed_lengths, color, shadow_value->has_inset()));
  }

  computed_shadow_ = new PropertyListValue(std::move(builder));
}

// Computed value: for length of translation transforms.
//   https://www.w3.org/TR/css3-transforms/#propdef-transform
class ComputedTransformFunctionProvider : public TransformFunctionVisitor {
 public:
  ComputedTransformFunctionProvider(const LengthValue* computed_font_size,
                                    const LengthValue* root_computed_font_size,
                                    const math::Size& viewport_size);

  void VisitMatrix(const MatrixFunction* matrix_function) override;
  void VisitRotate(const RotateFunction* rotate_function) override;
  void VisitScale(const ScaleFunction* scale_function) override;
  void VisitTranslate(const TranslateFunction* translate_function) override;
  void VisitCobaltUiNavFocusTransform(
      const CobaltUiNavFocusTransformFunction* focus_function) override;
  void VisitCobaltUiNavSpotlightTransform(
      const CobaltUiNavSpotlightTransformFunction* spotlight_function) override;

  std::unique_ptr<TransformFunction> PassComputedTransformFunction() {
    return std::move(computed_transform_function_);
  }

 private:
  std::unique_ptr<TransformFunction> computed_transform_function_;
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;
};

ComputedTransformFunctionProvider::ComputedTransformFunctionProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedTransformFunctionProvider::VisitMatrix(
    const MatrixFunction* matrix_function) {
  computed_transform_function_.reset(new MatrixFunction(*matrix_function));
}

void ComputedTransformFunctionProvider::VisitRotate(
    const RotateFunction* rotate_function) {
  computed_transform_function_.reset(new RotateFunction(*rotate_function));
}

void ComputedTransformFunctionProvider::VisitScale(
    const ScaleFunction* scale_function) {
  computed_transform_function_.reset(new ScaleFunction(*scale_function));
}

void ComputedTransformFunctionProvider::VisitTranslate(
    const TranslateFunction* translate_function) {
  switch (translate_function->offset_type()) {
    case TranslateFunction::kLength: {
      computed_transform_function_.reset(new TranslateFunction(
          translate_function->axis(),
          ProvideAbsoluteLength(translate_function->offset_as_length(),
                                computed_font_size_, root_computed_font_size_,
                                viewport_size_)));
    } break;
    case TranslateFunction::kPercentage: {
      computed_transform_function_.reset(
          new TranslateFunction(*translate_function));
    } break;
    case TranslateFunction::kCalc: {
      scoped_refptr<CalcValue> calc_value =
          translate_function->offset_as_calc();
      computed_transform_function_.reset(new TranslateFunction(
          translate_function->axis(),
          new CalcValue(ProvideAbsoluteLength(
                            calc_value->length_value(), computed_font_size_,
                            root_computed_font_size_, viewport_size_),
                        calc_value->percentage_value())));
    } break;
  }
}

void ComputedTransformFunctionProvider::VisitCobaltUiNavFocusTransform(
    const CobaltUiNavFocusTransformFunction* focus_function) {
  computed_transform_function_.reset(
      new CobaltUiNavFocusTransformFunction(*focus_function));
}

void ComputedTransformFunctionProvider::VisitCobaltUiNavSpotlightTransform(
    const CobaltUiNavSpotlightTransformFunction* spotlight_function) {
  computed_transform_function_.reset(
      new CobaltUiNavSpotlightTransformFunction(*spotlight_function));
}

// Absolutizes the value of "text-indent" property.
class ComputedTextIndentProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedTextIndentProvider(const LengthValue* computed_font_size,
                             const LengthValue* root_computed_font_size,
                             const math::Size& viewport_size);

  void VisitLength(LengthValue* length) override;

  const scoped_refptr<LengthValue>& computed_text_indent() const {
    return computed_text_indent_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<LengthValue> computed_text_indent_;

  DISALLOW_COPY_AND_ASSIGN(ComputedTextIndentProvider);
};

ComputedTextIndentProvider::ComputedTextIndentProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedTextIndentProvider::VisitLength(LengthValue* specified_length) {
  computed_text_indent_ =
      ProvideAbsoluteLength(specified_length, computed_font_size_,
                            root_computed_font_size_, viewport_size_);
}

// ComputedTransformOriginProvider provides a property list which has three
// PropertyValues. The first two PropertyValues are CalcValue to represent
// the horizontal position (or offset) and the vertical position (or offset).
// The third value always represents the Z position (or offset) and must be a
// LengthValue.
//  https://www.w3.org/TR/css3-transforms/#propdef-transform-origin
class ComputedTransformOriginProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedTransformOriginProvider(const LengthValue* computed_font_size,
                                  const LengthValue* root_computed_font_size,
                                  const math::Size& viewport_size);

  void VisitPropertyList(PropertyListValue* property_list_value) override;

  const scoped_refptr<PropertyValue>& computed_transform_origin() const {
    return computed_transform_origin_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_transform_origin_;

  DISALLOW_COPY_AND_ASSIGN(ComputedTransformOriginProvider);
};

ComputedTransformOriginProvider::ComputedTransformOriginProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedTransformOriginProvider::VisitPropertyList(
    PropertyListValue* property_list_value) {
  size_t size = property_list_value->value().size();
  DCHECK_GE(size, 1u);
  DCHECK_LE(size, 3u);

  ComputedPositionHelper position_helper(
      computed_font_size_, root_computed_font_size_, viewport_size_);
  std::unique_ptr<PropertyListValue::Builder> transform_origin_builder(
      new PropertyListValue::Builder(3, scoped_refptr<PropertyValue>()));

  // If one or two values are specified, the third value is assumed to be 0px.
  switch (size) {
    case 1:
    case 2:
      position_helper.ComputePosition(property_list_value->value(),
                                      transform_origin_builder.get());
      (*transform_origin_builder)[2] = new LengthValue(0.0f, kPixelsUnit);
      break;
    case 3:
      position_helper.ComputeTwoValuesPosition(property_list_value->value(),
                                               transform_origin_builder.get());
      // The third value must be LengthValue type.
      (*transform_origin_builder)[2] = ProvideAbsoluteLength(
          base::polymorphic_downcast<LengthValue*>(
              property_list_value->value()[2].get()),
          computed_font_size_, root_computed_font_size_, viewport_size_);
      break;
  }

  computed_transform_origin_ =
      new PropertyListValue(std::move(transform_origin_builder));
}

class ComputedTransformProvider : public NotReachedPropertyValueVisitor {
 public:
  ComputedTransformProvider(const LengthValue* computed_font_size,
                            const LengthValue* root_computed_font_size,
                            const math::Size& viewport_size);

  void VisitKeyword(KeywordValue* keyword) override;
  void VisitTransformPropertyValue(
      TransformPropertyValue* transform_property_value) override;

  const scoped_refptr<PropertyValue>& computed_transform_list() const {
    return computed_transform_list_;
  }

 private:
  const LengthValue* computed_font_size_;
  const LengthValue* root_computed_font_size_;
  const math::Size& viewport_size_;

  scoped_refptr<PropertyValue> computed_transform_list_;

  DISALLOW_COPY_AND_ASSIGN(ComputedTransformProvider);
};

ComputedTransformProvider::ComputedTransformProvider(
    const LengthValue* computed_font_size,
    const LengthValue* root_computed_font_size, const math::Size& viewport_size)
    : computed_font_size_(computed_font_size),
      root_computed_font_size_(root_computed_font_size),
      viewport_size_(viewport_size) {}

void ComputedTransformProvider::VisitTransformPropertyValue(
    TransformPropertyValue* transform_property_value) {
  // This should only ever be a TransformFunctionListValue at this point.
  TransformFunctionListValue* transform_function_list =
      base::polymorphic_downcast<TransformFunctionListValue*>(
          transform_property_value);
  if (!transform_function_list->value().HasTrait(
          TransformFunction::kTraitUsesRelativeUnits)) {
    // If the transform list contains no transforms that use relative units,
    // then we do not need to do anything and we can pass through the existing
    // transform.
    computed_transform_list_ = transform_function_list;
  } else {
    // The transform list contains at least one transform with relative units.
    // In this case, rebuild the transform list with computed length values.
    TransformFunctionListValue::Builder computed_list_builder;

    for (TransformFunctionListValue::Builder::const_iterator iter =
             transform_function_list->value().begin();
         iter != transform_function_list->value().end(); ++iter) {
      TransformFunction* transform_function = iter->get();

      ComputedTransformFunctionProvider computed_transform_function_provider(
          computed_font_size_, root_computed_font_size_, viewport_size_);
      transform_function->Accept(&computed_transform_function_provider);

      computed_list_builder.push_back(
          computed_transform_function_provider.PassComputedTransformFunction());
    }

    computed_transform_list_ =
        new TransformFunctionListValue(std::move(computed_list_builder));
  }
}

void ComputedTransformProvider::VisitKeyword(KeywordValue* keyword) {
  switch (keyword->value()) {
    case KeywordValue::kNone:
      computed_transform_list_ = keyword;
      break;

    default:
      NOTREACHED();
  }
}

// This helper class creates a context within which cascaded style properties
// can be efficiently promoted to computed properties.
// In particular, some computed style calculations depend on other computed
// styles, and this class manages the caching of those dependent values so that
// if they are depended upon more than once, they are quickly recalled, and if
// they are never depended upon, no extra time is spend resolving them.  For
// example, many properties depend on font size, and so they can simply call
// CalculateComputedStyleContext::GetFontSize() to obtain that value, and all
// computations will be handled internally.
class CalculateComputedStyleContext {
 public:
  CalculateComputedStyleContext(
      MutableCSSComputedStyleData* cascaded_style,
      const scoped_refptr<CSSComputedStyleDeclaration>&
          parent_computed_style_declaration,
      const scoped_refptr<const CSSComputedStyleData>& root_computed_style,
      const math::Size& viewport_size,
      GURLMap* const property_key_to_base_url_map)
      : cascaded_style_(cascaded_style),
        parent_computed_style_(*parent_computed_style_declaration->data()),
        root_computed_style_(*root_computed_style),
        viewport_size_(viewport_size),
        property_key_to_base_url_map_(property_key_to_base_url_map) {
    cascaded_style_->SetParentComputedStyleDeclaration(
        parent_computed_style_declaration);
  }

  // Updates the property specified by the iterator to its computed value.
  void SetComputedStyleForProperty(PropertyKey key,
                                   scoped_refptr<PropertyValue>* value);

  // For certain elements, the computed value of display becomes 'block'.
  //   https://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo
  // This is amended by flexbox for 'inline-flex' and 'flex'.
  //   https://www.w3.org/TR/css-flexbox-1/#flex-containers
  // Flex items are also modified in this way.
  //   https://www.w3.org/TR/css-flexbox-1/#flex-items
  // In CSS Display 3 (which Cobalt does not yet implement), this process is
  // called 'blockification'/'blockify'.
  //   https://www.w3.org/TR/css-display-3/#blockify
  void BlockifyIfNeeded();

 private:
  // Immediately promote the specified property key to computed value (if
  // necessary).
  void ComputeValue(PropertyKey key);

  // Check if the property value is set to inherit or initial, and assign it
  // an appropriate computed value in this case.
  bool HandleInheritOrInitial(PropertyKey key,
                              scoped_refptr<PropertyValue>* value);

  // Check what property property we are dealing with, and promote it to
  // a computed value accordingly (e.g. by invoking one of the many different
  // computed style computations defined above.)
  void HandleSpecifiedValue(PropertyKey key,
                            scoped_refptr<PropertyValue>* value);

  // If the modified value was a (potentially) dependent property value, cache
  // its computed value so that we know it has been computed.
  void OnComputedStyleCalculated(PropertyKey key,
                                 const scoped_refptr<PropertyValue>& value);

  // Helper function to determine if the computed style implies absolute
  // positioning.
  bool IsAbsolutelyPositioned();

  // Helper function to return the computed font size.
  LengthValue* GetFontSize();
  // Helper function to return the computed font size of root element.
  LengthValue* GetRootFontSize();
  // Helper function to return one percent of the viewport size .
  const math::Size& GetViewportSizeOnePercent();

  // Helper function to return the computed border style for an edge based on
  // border width properties.
  PropertyValue* GetBorderOrOutlineStyleBasedOnWidth(PropertyKey key);
  PropertyValue* GetBorderBottomStyle();
  PropertyValue* GetBorderLeftStyle();
  PropertyValue* GetBorderRightStyle();
  PropertyValue* GetBorderTopStyle();
  PropertyValue* GetOutlineStyle();

  // Helper function to return the computed color.
  RGBAColorValue* GetColor();

  // The style that, during the scope of CalculateComputedStyleContext, is
  // promoted from being a cascaded style to a computed style.
  MutableCSSComputedStyleData* cascaded_style_;

  // The parent computed style.
  const CSSComputedStyleData& parent_computed_style_;
  // The root computed style.
  const CSSComputedStyleData& root_computed_style_;

  // One percent of width and height of viewport size.
  const math::Size& viewport_size_;

  // Provides a base URL for each property key.  This is used by properties
  // that deal with URLs, such as background-image, to resolve relative URLs
  // based on which style sheet they were specified from.
  GURLMap* const property_key_to_base_url_map_;

  // Cached computed values for a small specific set of properties that other
  // properties computed style calculations depend upon.  These are lazily
  // computed.
  scoped_refptr<PropertyValue> computed_border_bottom_style_;
  scoped_refptr<PropertyValue> computed_border_left_style_;
  scoped_refptr<PropertyValue> computed_border_right_style_;
  scoped_refptr<PropertyValue> computed_border_top_style_;
  scoped_refptr<PropertyValue> computed_color_;
  scoped_refptr<PropertyValue> computed_font_size_;
  scoped_refptr<PropertyValue> computed_outline_style_;
  scoped_refptr<PropertyValue> computed_position_;
};

void CalculateComputedStyleContext::SetComputedStyleForProperty(
    PropertyKey key, scoped_refptr<PropertyValue>* value) {
  // If a property has keyword value 'inherit' or 'initial', it must be
  // set to the corresponding inherited or initial value.  In this case,
  // the parent's value is already computed so we can skip the computation
  // step.
  if (!HandleInheritOrInitial(key, value)) {
    HandleSpecifiedValue(key, value);
  }
  OnComputedStyleCalculated(key, *value);
}

void CalculateComputedStyleContext::BlockifyIfNeeded() {
  auto display = cascaded_style_->display();
  bool is_inline_flex = display == KeywordValue::GetInlineFlex();
  bool is_inline = display == KeywordValue::GetInline() ||
                   display == KeywordValue::GetInlineBlock() || is_inline_flex;
  auto parent_display = parent_computed_style_.display();
  bool parent_is_flex_container =
      parent_display == KeywordValue::GetFlex() ||
      parent_display == KeywordValue::GetInlineFlex();

  // Blockification is applied for elements with in inline outer display type
  // inline when they are either absolutely positioned,
  //   https://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo
  // or when they are flex items.
  //   https://www.w3.org/TR/css-flexbox-1/#flex-items
  // Since children of flex containers are either flex items or absolutely
  // positioned, we apply blockification for all flex children.
  if (is_inline && (IsAbsolutelyPositioned() || parent_is_flex_container)) {
    if (is_inline_flex) {
      cascaded_style_->set_display(KeywordValue::GetFlex());
    } else {
      cascaded_style_->set_display(KeywordValue::GetBlock());
    }
  }
  cascaded_style_->set_is_inline_before_blockification(is_inline);
}

bool CalculateComputedStyleContext::IsAbsolutelyPositioned() {
  // An absolutely positioned element (or its box) implies that the element's
  // 'position' property has the value 'absolute' or 'fixed'.
  //   https://www.w3.org/TR/CSS21/visuren.html#absolutely-positioned
  if (!computed_position_) {
    ComputeValue(kPositionProperty);
  }

  DCHECK(computed_position_);
  return computed_position_ == KeywordValue::GetAbsolute() ||
         computed_position_ == KeywordValue::GetFixed();
}

LengthValue* CalculateComputedStyleContext::GetFontSize() {
  if (!computed_font_size_) {
    ComputeValue(kFontSizeProperty);
  }

  DCHECK(computed_font_size_);
  return base::polymorphic_downcast<LengthValue*>(computed_font_size_.get());
}

LengthValue* CalculateComputedStyleContext::GetRootFontSize() {
  return base::polymorphic_downcast<LengthValue*>(
      root_computed_style_.font_size().get());
}

const math::Size& CalculateComputedStyleContext::GetViewportSizeOnePercent() {
  return viewport_size_;
}

PropertyValue*
CalculateComputedStyleContext::GetBorderOrOutlineStyleBasedOnWidth(
    PropertyKey key) {
  if (key == kBorderBottomWidthProperty) {
    return GetBorderBottomStyle();
  } else if (key == kBorderLeftWidthProperty) {
    return GetBorderLeftStyle();
  } else if (key == kBorderRightWidthProperty) {
    return GetBorderRightStyle();
  } else if (key == kBorderTopWidthProperty) {
    return GetBorderTopStyle();
  } else {
    DCHECK_EQ(key, kOutlineWidthProperty);
    return GetOutlineStyle();
  }
}

PropertyValue* CalculateComputedStyleContext::GetBorderBottomStyle() {
  if (!computed_border_bottom_style_) {
    ComputeValue(kBorderBottomStyleProperty);
  }

  DCHECK(computed_border_bottom_style_);
  return computed_border_bottom_style_.get();
}

PropertyValue* CalculateComputedStyleContext::GetBorderLeftStyle() {
  if (!computed_border_left_style_) {
    ComputeValue(kBorderLeftStyleProperty);
  }

  DCHECK(computed_border_left_style_);
  return computed_border_left_style_.get();
}

PropertyValue* CalculateComputedStyleContext::GetBorderRightStyle() {
  if (!computed_border_right_style_) {
    ComputeValue(kBorderRightStyleProperty);
  }

  DCHECK(computed_border_right_style_);
  return computed_border_right_style_.get();
}

PropertyValue* CalculateComputedStyleContext::GetBorderTopStyle() {
  if (!computed_border_top_style_) {
    ComputeValue(kBorderTopStyleProperty);
  }

  DCHECK(computed_border_top_style_);
  return computed_border_top_style_.get();
}

RGBAColorValue* CalculateComputedStyleContext::GetColor() {
  if (!computed_color_) {
    ComputeValue(kColorProperty);
  }

  DCHECK(computed_color_);
  return base::polymorphic_downcast<RGBAColorValue*>(computed_color_.get());
}

PropertyValue* CalculateComputedStyleContext::GetOutlineStyle() {
  if (!computed_outline_style_) {
    ComputeValue(kOutlineStyleProperty);
  }

  DCHECK(computed_outline_style_);
  return computed_outline_style_.get();
}

void CalculateComputedStyleContext::ComputeValue(PropertyKey key) {
  if (cascaded_style_->IsDeclared(key)) {
    scoped_refptr<PropertyValue>& cascaded_value =
        cascaded_style_->GetDeclaredPropertyValueReference(key);
    SetComputedStyleForProperty(key, &cascaded_value);
  } else {
    const scoped_refptr<PropertyValue>& computed_value =
        cascaded_style_->GetPropertyValueReference(key);
    OnComputedStyleCalculated(key, computed_value);
  }
}

bool CalculateComputedStyleContext::HandleInheritOrInitial(
    PropertyKey key, scoped_refptr<PropertyValue>* value) {
  if (*value == KeywordValue::GetInherit()) {
    // Add this property to the list of those that inherited their declared
    // value from the parent. This allows the computed style to later determine
    // if a value that was explicitly inherited from the parent is no longer
    // valid.
    cascaded_style_->AddDeclaredPropertyInheritedFromParent(key);
    *value = parent_computed_style_.GetPropertyValue(key);
    return true;
  } else if (*value == KeywordValue::GetInitial()) {
    *value = GetPropertyInitialValue(key);
    // If the initial value is current color, it still requires to do further
    // processing.
    return *value == KeywordValue::GetCurrentColor() ? false : true;
  } else {
    return false;
  }
}

void CalculateComputedStyleContext::HandleSpecifiedValue(
    PropertyKey key, scoped_refptr<PropertyValue>* value) {
  switch (key) {
    case kBackgroundPositionProperty: {
      ComputedBackgroundPositionProvider background_position_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&background_position_provider);
      const scoped_refptr<PropertyValue>& computed_background_position =
          background_position_provider.computed_background_position();
      if (computed_background_position) {
        *value = computed_background_position;
      }
    } break;
    case kBorderBottomColorProperty:
    case kBorderLeftColorProperty:
    case kBorderRightColorProperty:
    case kBorderTopColorProperty:
    case kOutlineColorProperty:
    case kTextDecorationColorProperty: {
      if (*value == KeywordValue::GetCurrentColor()) {
        // The computed value of the 'currentColor' keyword is the computed
        // value of the 'color' property.
        *value = GetColor();
      }
    } break;
    case kBorderBottomWidthProperty:
    case kBorderLeftWidthProperty:
    case kBorderRightWidthProperty:
    case kBorderTopWidthProperty:
    case kOutlineWidthProperty: {
      ComputedBorderWidthProvider border_width_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent(),
          GetBorderOrOutlineStyleBasedOnWidth(key));
      (*value)->Accept(&border_width_provider);
      *value = border_width_provider.computed_border_width();
    } break;
    case kBoxShadowProperty:
    case kTextShadowProperty: {
      ComputedShadowProvider shadow_provider(GetFontSize(), GetRootFontSize(),
                                             GetViewportSizeOnePercent(),
                                             GetColor());
      (*value)->Accept(&shadow_provider);
      *value = shadow_provider.computed_shadow();
    } break;
    case kFlexBasisProperty: {
      ComputedFlexBasisProvider flex_basis_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&flex_basis_provider);
      *value = flex_basis_provider.computed_value();
    } break;
    case kFontSizeProperty: {
      // Only compute this if computed_font_size_ isn't set, otherwise that
      // is an indication that it was previously computed as a dependency for
      // another property value computation.
      if (!computed_font_size_) {
        ComputedFontSizeProvider font_size_provider(
            base::polymorphic_downcast<LengthValue*>(
                parent_computed_style_.font_size().get()),
            GetRootFontSize(), GetViewportSizeOnePercent());
        (*value)->Accept(&font_size_provider);
        if (font_size_provider.computed_font_size()) {
          *value = font_size_provider.computed_font_size();
        }
      }
    } break;
    case kFontWeightProperty: {
      ComputedFontWeightProvider font_weight_provider;
      (*value)->Accept(&font_weight_provider);
      *value = font_weight_provider.computed_font_weight();
    } break;
    case kHeightProperty: {
      ComputedHeightProvider height_provider(
          parent_computed_style_.height().get(),
          parent_computed_style_.top().get(),
          parent_computed_style_.bottom().get(), GetFontSize(),
          GetRootFontSize(), GetViewportSizeOnePercent(),
          IsAbsolutelyPositioned());
      (*value)->Accept(&height_provider);
      *value = height_provider.computed_height();
    } break;
    case kLineHeightProperty: {
      ComputedLineHeightProvider line_height_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&line_height_provider);
      *value = line_height_provider.computed_line_height();
    } break;
    case kMarginBottomProperty:
    case kMarginLeftProperty:
    case kMarginRightProperty:
    case kMarginTopProperty: {
      ComputedMarginOrPaddingEdgeProvider margin_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&margin_provider);
      *value = margin_provider.computed_margin_or_padding_edge();
    } break;
    case kPaddingBottomProperty:
    case kPaddingLeftProperty:
    case kPaddingRightProperty:
    case kPaddingTopProperty: {
      ComputedMarginOrPaddingEdgeProvider padding_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&padding_provider);
      *value = padding_provider.computed_margin_or_padding_edge();
    } break;
    case kMaxHeightProperty: {
      ComputedMaxHeightProvider max_height_provider(
          parent_computed_style_.height().get(), GetFontSize(),
          GetRootFontSize(), GetViewportSizeOnePercent(),
          IsAbsolutelyPositioned());
      (*value)->Accept(&max_height_provider);
      *value = max_height_provider.computed_max_height();
    } break;
    case kMinHeightProperty: {
      ComputedMinHeightProvider min_height_provider(
          parent_computed_style_.height().get(), GetFontSize(),
          GetRootFontSize(), GetViewportSizeOnePercent(),
          IsAbsolutelyPositioned());
      (*value)->Accept(&min_height_provider);
      *value = min_height_provider.computed_min_height();
    } break;
    case kMaxWidthProperty:
    case kMinWidthProperty: {
      ComputedMinMaxWidthProvider min_max_width_provider(
          parent_computed_style_.width().get(), GetFontSize(),
          GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&min_max_width_provider);
      *value = min_max_width_provider.computed_min_max_width();
    } break;
    case kWidthProperty: {
      ComputedWidthProvider width_provider(GetFontSize(), GetRootFontSize(),
                                           GetViewportSizeOnePercent());
      (*value)->Accept(&width_provider);
      *value = width_provider.computed_value();
    } break;
    case kBackgroundImageProperty: {
      if (property_key_to_base_url_map_) {
        ComputedBackgroundImageProvider background_image_provider(
            (*property_key_to_base_url_map_)[kBackgroundImageProperty],
            GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
        (*value)->Accept(&background_image_provider);
        *value = background_image_provider.computed_background_image();
      }
    } break;
    case kBackgroundSizeProperty: {
      ComputedBackgroundSizeProvider background_size_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&background_size_provider);
      *value = background_size_provider.computed_background_size();
    } break;
    case kBorderBottomLeftRadiusProperty:
    case kBorderBottomRightRadiusProperty:
    case kBorderTopLeftRadiusProperty:
    case kBorderTopRightRadiusProperty: {
      ComputedBorderRadiusProvider border_radius_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&border_radius_provider);
      *value = border_radius_provider.computed_border_radius();
    } break;
    case kTextIndentProperty: {
      ComputedTextIndentProvider text_indent_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&text_indent_provider);
      *value = text_indent_provider.computed_text_indent();
    } break;
    case kTransformOriginProperty: {
      ComputedTransformOriginProvider transform_origin_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&transform_origin_provider);
      *value = transform_origin_provider.computed_transform_origin();
    } break;
    case kTransformProperty: {
      ComputedTransformProvider transform_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&transform_provider);
      *value = transform_provider.computed_transform_list();
    } break;
    case kBottomProperty:
    case kLeftProperty:
    case kRightProperty:
    case kTopProperty: {
      ComputedPositionOffsetProvider position_offset_provider(
          GetFontSize(), GetRootFontSize(), GetViewportSizeOnePercent());
      (*value)->Accept(&position_offset_provider);
      *value = position_offset_provider.computed_position_offset();
    } break;

    // The specified value resolves directly to the computed value for the
    // remaining longhand properties. Shorthand properties and at-rule
    // properties should not occur here because they do not have computed values
    // themselves.
    default:
      // Nothing.
      break;
  }
}  // NOLINT(readability/fn_size)

void CalculateComputedStyleContext::OnComputedStyleCalculated(
    PropertyKey key, const scoped_refptr<PropertyValue>& value) {
  switch (key) {
    case kFontSizeProperty:
      computed_font_size_ = value;
      break;
    case kPositionProperty:
      computed_position_ = value;
      break;
    case kBorderBottomStyleProperty:
      computed_border_bottom_style_ = value;
      break;
    case kBorderLeftStyleProperty:
      computed_border_left_style_ = value;
      break;
    case kBorderRightStyleProperty:
      computed_border_right_style_ = value;
      break;
    case kBorderTopStyleProperty:
      computed_border_top_style_ = value;
      break;
    case kColorProperty:
      computed_color_ = value;
      break;
    case kOutlineStyleProperty:
      computed_outline_style_ = value;
      break;

    default:
      break;
  }
}

}  // namespace

void PromoteToComputedStyle(
    const scoped_refptr<MutableCSSComputedStyleData>& cascaded_style,
    const scoped_refptr<CSSComputedStyleDeclaration>&
        parent_computed_style_declaration,
    const scoped_refptr<const CSSComputedStyleData>& root_computed_style,
    const math::Size& viewport_size,
    GURLMap* const property_key_to_base_url_map) {
  DCHECK(cascaded_style);
  DCHECK(parent_computed_style_declaration);
  DCHECK(root_computed_style);
  if (!cascaded_style || !root_computed_style ||
      !parent_computed_style_declaration) {
    return;
  }
  // Create a context for calculating the computed style.  This object is
  // useful because it can cache computed style values that are depended upon
  // by other properties' computed style calculations.
  CalculateComputedStyleContext calculate_computed_style_context(
      cascaded_style.get(), parent_computed_style_declaration,
      root_computed_style, viewport_size, property_key_to_base_url_map);

  // For each inherited, animatable property, set the property value to
  // inherited if it is not already declared. This causes the value to be
  // explicitly set within the CSSComputedStyleData and ensures that the
  // original value will be available for transitions (which need to know the
  // before and after state of the property) even when the property is inherited
  // from a parent that has changed.
  const PropertyKeyVector& inherited_animatable_properties =
      GetInheritedAnimatableProperties();
  for (PropertyKeyVector::const_iterator iter =
           inherited_animatable_properties.begin();
       iter != inherited_animatable_properties.end(); ++iter) {
    if (!cascaded_style->IsDeclared(*iter)) {
      cascaded_style->SetPropertyValue(*iter, KeywordValue::GetInherit());
    }
  }

  // Go through all declared values and calculate their computed values.
  CSSComputedStyleData::PropertyValues* declared_property_values =
      cascaded_style->declared_property_values();
  for (CSSComputedStyleData::PropertyValues::iterator property_value_iterator =
           declared_property_values->begin();
       property_value_iterator != declared_property_values->end();
       ++property_value_iterator) {
    calculate_computed_style_context.SetComputedStyleForProperty(
        property_value_iterator->first, &property_value_iterator->second);
  }

  calculate_computed_style_context.BlockifyIfNeeded();
}

scoped_refptr<CSSComputedStyleData> GetComputedStyleOfAnonymousBox(
    const scoped_refptr<CSSComputedStyleDeclaration>&
        parent_computed_style_declaration) {
  scoped_refptr<MutableCSSComputedStyleData> computed_style =
      new MutableCSSComputedStyleData();
  PromoteToComputedStyle(computed_style, parent_computed_style_declaration,
                         parent_computed_style_declaration->data(),
                         math::Size(), NULL);
  return computed_style;
}

}  // namespace cssom
}  // namespace cobalt
