/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "core/layout/LayoutReplaced.h"

#include "core/editing/PositionWithAffinity.h"
#include "core/layout/LayoutAnalyzer.h"
#include "core/layout/LayoutBlock.h"
#include "core/layout/LayoutImage.h"
#include "core/layout/LayoutInline.h"
#include "core/layout/LayoutPart.h"
#include "core/layout/LayoutVideo.h"
#include "core/layout/api/LineLayoutBlockFlow.h"
#include "core/paint/PaintInfo.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/ReplacedPainter.h"
#include "platform/LengthFunctions.h"

namespace blink {

const int LayoutReplaced::defaultWidth = 300;
const int LayoutReplaced::defaultHeight = 150;

LayoutReplaced::LayoutReplaced(Element* element)
    : LayoutBox(element), m_intrinsicSize(defaultWidth, defaultHeight) {
  // TODO(jchaffraix): We should not set this boolean for block-level
  // replaced elements (crbug.com/567964).
  setIsAtomicInlineLevel(true);
}

LayoutReplaced::LayoutReplaced(Element* element,
                               const LayoutSize& intrinsicSize)
    : LayoutBox(element), m_intrinsicSize(intrinsicSize) {
  // TODO(jchaffraix): We should not set this boolean for block-level
  // replaced elements (crbug.com/567964).
  setIsAtomicInlineLevel(true);
}

LayoutReplaced::~LayoutReplaced() {}

void LayoutReplaced::willBeDestroyed() {
  if (!documentBeingDestroyed() && parent())
    parent()->dirtyLinesFromChangedChild(this);

  LayoutBox::willBeDestroyed();
}

void LayoutReplaced::styleDidChange(StyleDifference diff,
                                    const ComputedStyle* oldStyle) {
  LayoutBox::styleDidChange(diff, oldStyle);

  bool hadStyle = (oldStyle != 0);
  float oldZoom =
      hadStyle ? oldStyle->effectiveZoom() : ComputedStyle::initialZoom();
  if (style() && style()->effectiveZoom() != oldZoom)
    intrinsicSizeChanged();
}

void LayoutReplaced::layout() {
  ASSERT(needsLayout());
  LayoutAnalyzer::Scope analyzer(*this);

  LayoutRect oldContentRect = replacedContentRect();

  setHeight(minimumReplacedHeight());

  updateLogicalWidth();
  updateLogicalHeight();

  m_overflow.reset();
  addVisualEffectOverflow();
  updateLayerTransformAfterLayout();
  invalidateBackgroundObscurationStatus();

  clearNeedsLayout();

  if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled() &&
      replacedContentRect() != oldContentRect)
    setShouldDoFullPaintInvalidation();
}

void LayoutReplaced::intrinsicSizeChanged() {
  int scaledWidth = static_cast<int>(defaultWidth * style()->effectiveZoom());
  int scaledHeight = static_cast<int>(defaultHeight * style()->effectiveZoom());
  m_intrinsicSize = LayoutSize(scaledWidth, scaledHeight);
  setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
      LayoutInvalidationReason::SizeChanged);
}

void LayoutReplaced::paint(const PaintInfo& paintInfo,
                           const LayoutPoint& paintOffset) const {
  ReplacedPainter(*this).paint(paintInfo, paintOffset);
}

bool LayoutReplaced::hasReplacedLogicalHeight() const {
  if (style()->logicalHeight().isAuto())
    return false;

  if (style()->logicalHeight().isSpecified()) {
    if (hasAutoHeightOrContainingBlockWithAutoHeight())
      return false;
    return true;
  }

  if (style()->logicalHeight().isIntrinsic())
    return true;

  return false;
}

bool LayoutReplaced::needsPreferredWidthsRecalculation() const {
  // If the height is a percentage and the width is auto, then the
  // containingBlocks's height changing can cause this node to change it's
  // preferred width because it maintains aspect ratio.
  return hasRelativeLogicalHeight() && style()->logicalWidth().isAuto() &&
         !hasAutoHeightOrContainingBlockWithAutoHeight();
}

static inline bool layoutObjectHasAspectRatio(
    const LayoutObject* layoutObject) {
  ASSERT(layoutObject);
  return layoutObject->isImage() || layoutObject->isCanvas() ||
         layoutObject->isVideo();
}

void LayoutReplaced::computeIntrinsicSizingInfoForReplacedContent(
    LayoutReplaced* contentLayoutObject,
    IntrinsicSizingInfo& intrinsicSizingInfo) const {
  if (contentLayoutObject) {
    contentLayoutObject->computeIntrinsicSizingInfo(intrinsicSizingInfo);

    // Handle zoom & vertical writing modes here, as the embedded document
    // doesn't know about them.
    intrinsicSizingInfo.size.scale(style()->effectiveZoom());
    if (isLayoutImage())
      intrinsicSizingInfo.size.scale(
          toLayoutImage(this)->imageDevicePixelRatio());

    // Update our intrinsic size to match what the content layoutObject has
    // computed, so that when we constrain the size below, the correct intrinsic
    // size will be obtained for comparison against min and max widths.
    if (!intrinsicSizingInfo.aspectRatio.isEmpty() &&
        !intrinsicSizingInfo.size.isEmpty())
      m_intrinsicSize = LayoutSize(intrinsicSizingInfo.size);

    if (!isHorizontalWritingMode())
      intrinsicSizingInfo.transpose();
  } else {
    computeIntrinsicSizingInfo(intrinsicSizingInfo);
    if (!intrinsicSizingInfo.aspectRatio.isEmpty() &&
        !intrinsicSizingInfo.size.isEmpty())
      m_intrinsicSize =
          LayoutSize(isHorizontalWritingMode()
                         ? intrinsicSizingInfo.size
                         : intrinsicSizingInfo.size.transposedSize());
  }
}

FloatSize LayoutReplaced::constrainIntrinsicSizeToMinMax(
    const IntrinsicSizingInfo& intrinsicSizingInfo) const {
  // Constrain the intrinsic size along each axis according to minimum and
  // maximum width/heights along the opposite axis. So for example a maximum
  // width that shrinks our width will result in the height we compute here
  // having to shrink in order to preserve the aspect ratio. Because we compute
  // these values independently along each axis, the final returned size may in
  // fact not preserve the aspect ratio.
  // TODO(davve): Investigate using only the intrinsic aspect ratio here.
  FloatSize constrainedSize = intrinsicSizingInfo.size;
  if (!intrinsicSizingInfo.aspectRatio.isEmpty() &&
      !intrinsicSizingInfo.size.isEmpty() && style()->logicalWidth().isAuto() &&
      style()->logicalHeight().isAuto()) {
    // We can't multiply or divide by 'intrinsicSizingInfo.aspectRatio' here, it
    // breaks tests, like images/zoomed-img-size.html, which
    // can only be fixed once subpixel precision is available for things like
    // intrinsicWidth/Height - which include zoom!
    constrainedSize.setWidth(LayoutBox::computeReplacedLogicalHeight() *
                             intrinsicSizingInfo.size.width() /
                             intrinsicSizingInfo.size.height());
    constrainedSize.setHeight(LayoutBox::computeReplacedLogicalWidth() *
                              intrinsicSizingInfo.size.height() /
                              intrinsicSizingInfo.size.width());
  }
  return constrainedSize;
}

void LayoutReplaced::computePositionedLogicalWidth(
    LogicalExtentComputedValues& computedValues) const {
  // The following is based off of the W3C Working Draft from April 11, 2006 of
  // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements"
  // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width>
  // (block-style-comments in this function correspond to text from the spec and
  // the numbers correspond to numbers in spec).

  // We don't use containingBlock(), since we may be positioned by an enclosing
  // relative positioned inline.
  const LayoutBoxModelObject* containerBlock =
      toLayoutBoxModelObject(container());

  const LayoutUnit containerLogicalWidth =
      containingBlockLogicalWidthForPositioned(containerBlock);
  const LayoutUnit containerRelativeLogicalWidth =
      containingBlockLogicalWidthForPositioned(containerBlock, false);

  // To match WinIE, in quirks mode use the parent's 'direction' property
  // instead of the the container block's.
  TextDirection containerDirection = containerBlock->style()->direction();

  // Variables to solve.
  bool isHorizontal = isHorizontalWritingMode();
  Length logicalLeft = style()->logicalLeft();
  Length logicalRight = style()->logicalRight();
  Length marginLogicalLeft =
      isHorizontal ? style()->marginLeft() : style()->marginTop();
  Length marginLogicalRight =
      isHorizontal ? style()->marginRight() : style()->marginBottom();
  LayoutUnit& marginLogicalLeftAlias = style()->isLeftToRightDirection()
                                           ? computedValues.m_margins.m_start
                                           : computedValues.m_margins.m_end;
  LayoutUnit& marginLogicalRightAlias = style()->isLeftToRightDirection()
                                            ? computedValues.m_margins.m_end
                                            : computedValues.m_margins.m_start;

  // ---------------------------------------------------------------------------
  // 1. The used value of 'width' is determined as for inline replaced
  //  elements.
  // ---------------------------------------------------------------------------
  // NOTE: This value of width is final in that the min/max width calculations
  // are dealt with in computeReplacedWidth().  This means that the steps to
  // produce correct max/min in the non-replaced version, are not necessary.
  computedValues.m_extent =
      computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth();

  const LayoutUnit availableSpace =
      containerLogicalWidth - computedValues.m_extent;

  // ---------------------------------------------------------------------------
  // 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
  //    of the containing block is 'ltr', set 'left' to the static position;
  //    else if 'direction' is 'rtl', set 'right' to the static position.
  // ---------------------------------------------------------------------------
  // see FIXME 1
  computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock,
                              containerLogicalWidth);

  // ---------------------------------------------------------------------------
  // 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
  //    or 'margin-right' with '0'.
  // ---------------------------------------------------------------------------
  if (logicalLeft.isAuto() || logicalRight.isAuto()) {
    if (marginLogicalLeft.isAuto())
      marginLogicalLeft.setValue(Fixed, 0);
    if (marginLogicalRight.isAuto())
      marginLogicalRight.setValue(Fixed, 0);
  }

  // ---------------------------------------------------------------------------
  // 4. If at this point both 'margin-left' and 'margin-right' are still 'auto',
  //    solve the equation under the extra constraint that the two margins must
  //    get equal values, unless this would make them negative, in which case
  //    when the direction of the containing block is 'ltr' ('rtl'), set
  //    'margin-left' ('margin-right') to zero and solve for 'margin-right'
  //    ('margin-left').
  // ---------------------------------------------------------------------------
  LayoutUnit logicalLeftValue;
  LayoutUnit logicalRightValue;

  if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
    // 'left' and 'right' cannot be 'auto' due to step 3
    ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));

    logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
    logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);

    LayoutUnit difference =
        availableSpace - (logicalLeftValue + logicalRightValue);
    if (difference > LayoutUnit()) {
      marginLogicalLeftAlias = difference / 2;  // split the difference
      marginLogicalRightAlias =
          difference -
          marginLogicalLeftAlias;  // account for odd valued differences
    } else {
      // Use the containing block's direction rather than the parent block's
      // per CSS 2.1 reference test abspos-replaced-width-margin-000.
      if (containerDirection == TextDirection::Ltr) {
        marginLogicalLeftAlias = LayoutUnit();
        marginLogicalRightAlias = difference;  // will be negative
      } else {
        marginLogicalLeftAlias = difference;  // will be negative
        marginLogicalRightAlias = LayoutUnit();
      }
    }

    // -------------------------------------------------------------------------
    // 5. If at this point there is an 'auto' left, solve the equation for that
    //    value.
    // -------------------------------------------------------------------------
  } else if (logicalLeft.isAuto()) {
    marginLogicalLeftAlias =
        valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
    marginLogicalRightAlias =
        valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
    logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);

    // Solve for 'left'
    logicalLeftValue =
        availableSpace -
        (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
  } else if (logicalRight.isAuto()) {
    marginLogicalLeftAlias =
        valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
    marginLogicalRightAlias =
        valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
    logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);

    // Solve for 'right'
    logicalRightValue =
        availableSpace -
        (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
  } else if (marginLogicalLeft.isAuto()) {
    marginLogicalRightAlias =
        valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
    logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
    logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);

    // Solve for 'margin-left'
    marginLogicalLeftAlias =
        availableSpace -
        (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
  } else if (marginLogicalRight.isAuto()) {
    marginLogicalLeftAlias =
        valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
    logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
    logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);

    // Solve for 'margin-right'
    marginLogicalRightAlias =
        availableSpace -
        (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
  } else {
    // Nothing is 'auto', just calculate the values.
    marginLogicalLeftAlias =
        valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
    marginLogicalRightAlias =
        valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
    logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
    logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
    // If the containing block is right-to-left, then push the left position as
    // far to the right as possible
    if (containerDirection == TextDirection::Rtl) {
      int totalLogicalWidth =
          (computedValues.m_extent + logicalLeftValue + logicalRightValue +
           marginLogicalLeftAlias + marginLogicalRightAlias)
              .toInt();
      logicalLeftValue =
          containerLogicalWidth - (totalLogicalWidth - logicalLeftValue);
    }
  }

  // ---------------------------------------------------------------------------
  // 6. If at this point the values are over-constrained, ignore the value for
  //    either 'left' (in case the 'direction' property of the containing block
  //    is 'rtl') or 'right' (in case 'direction' is 'ltr') and solve for that
  //    value.
  // ---------------------------------------------------------------------------
  // NOTE: Constraints imposed by the width of the containing block and its
  // content have already been accounted for above.
  //
  // FIXME: Deal with differing writing modes here.  Our offset needs to be in
  // the containing block's coordinate space, so that
  // can make the result here rather complicated to compute.
  //
  // Use computed values to calculate the horizontal position.
  //
  // FIXME: This hack is needed to calculate the logical left position for a
  // 'rtl' relatively positioned, inline containing block because right now, it
  // is using the logical left position of the first line box when really it
  // should use the last line box. When this is fixed elsewhere, this block
  // should be removed.
  if (containerBlock->isLayoutInline() &&
      !containerBlock->style()->isLeftToRightDirection()) {
    const LayoutInline* flow = toLayoutInline(containerBlock);
    InlineFlowBox* firstLine = flow->firstLineBox();
    InlineFlowBox* lastLine = flow->lastLineBox();
    if (firstLine && lastLine && firstLine != lastLine) {
      computedValues.m_position =
          logicalLeftValue + marginLogicalLeftAlias +
          lastLine->borderLogicalLeft() +
          (lastLine->logicalLeft() - firstLine->logicalLeft());
      return;
    }
  }

  LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias;
  computeLogicalLeftPositionedOffset(logicalLeftPos, this,
                                     computedValues.m_extent, containerBlock,
                                     containerLogicalWidth);
  computedValues.m_position = logicalLeftPos;
}

void LayoutReplaced::computePositionedLogicalHeight(
    LogicalExtentComputedValues& computedValues) const {
  // The following is based off of the W3C Working Draft from April 11, 2006 of
  // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements"
  // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height>
  // (block-style-comments in this function correspond to text from the spec and
  // the numbers correspond to numbers in spec)

  // We don't use containingBlock(), since we may be positioned by an enclosing
  // relpositioned inline.
  const LayoutBoxModelObject* containerBlock =
      toLayoutBoxModelObject(container());

  const LayoutUnit containerLogicalHeight =
      containingBlockLogicalHeightForPositioned(containerBlock);
  const LayoutUnit containerRelativeLogicalWidth =
      containingBlockLogicalWidthForPositioned(containerBlock, false);

  // Variables to solve.
  Length marginBefore = style()->marginBefore();
  Length marginAfter = style()->marginAfter();
  LayoutUnit& marginBeforeAlias = computedValues.m_margins.m_before;
  LayoutUnit& marginAfterAlias = computedValues.m_margins.m_after;

  Length logicalTop = style()->logicalTop();
  Length logicalBottom = style()->logicalBottom();

  // ---------------------------------------------------------------------------
  // 1. The used value of 'height' is determined as for inline replaced
  //    elements.
  // ---------------------------------------------------------------------------
  // NOTE: This value of height is final in that the min/max height calculations
  // are dealt with in computeReplacedHeight().  This means that the steps to
  // produce correct max/min in the non-replaced version, are not necessary.
  computedValues.m_extent =
      computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight();
  const LayoutUnit availableSpace =
      containerLogicalHeight - computedValues.m_extent;

  // ---------------------------------------------------------------------------
  // 2. If both 'top' and 'bottom' have the value 'auto', replace 'top' with the
  //    element's static position.
  // ---------------------------------------------------------------------------
  // see FIXME 1
  computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock);

  // ---------------------------------------------------------------------------
  // 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
  //    'margin-bottom' with '0'.
  // ---------------------------------------------------------------------------
  // FIXME: The spec. says that this step should only be taken when bottom is
  // auto, but if only top is auto, this makes step 4 impossible.
  if (logicalTop.isAuto() || logicalBottom.isAuto()) {
    if (marginBefore.isAuto())
      marginBefore.setValue(Fixed, 0);
    if (marginAfter.isAuto())
      marginAfter.setValue(Fixed, 0);
  }

  // ---------------------------------------------------------------------------
  // 4. If at this point both 'margin-top' and 'margin-bottom' are still 'auto',
  //    solve the equation under the extra constraint that the two margins must
  //    get equal values.
  // ---------------------------------------------------------------------------
  LayoutUnit logicalTopValue;
  LayoutUnit logicalBottomValue;

  if (marginBefore.isAuto() && marginAfter.isAuto()) {
    // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
    ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));

    logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
    logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);

    LayoutUnit difference =
        availableSpace - (logicalTopValue + logicalBottomValue);
    // NOTE: This may result in negative values.
    marginBeforeAlias = difference / 2;  // split the difference
    marginAfterAlias =
        difference - marginBeforeAlias;  // account for odd valued differences

    // -------------------------------------------------------------------------
    // 5. If at this point there is only one 'auto' left, solve the equation
    //    for that value.
    // -------------------------------------------------------------------------
  } else if (logicalTop.isAuto()) {
    marginBeforeAlias =
        valueForLength(marginBefore, containerRelativeLogicalWidth);
    marginAfterAlias =
        valueForLength(marginAfter, containerRelativeLogicalWidth);
    logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);

    // Solve for 'top'
    logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias +
                                        marginAfterAlias);
  } else if (logicalBottom.isAuto()) {
    marginBeforeAlias =
        valueForLength(marginBefore, containerRelativeLogicalWidth);
    marginAfterAlias =
        valueForLength(marginAfter, containerRelativeLogicalWidth);
    logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);

    // Solve for 'bottom'
    // NOTE: It is not necessary to solve for 'bottom' because we don't ever
    // use the value.
  } else if (marginBefore.isAuto()) {
    marginAfterAlias =
        valueForLength(marginAfter, containerRelativeLogicalWidth);
    logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
    logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);

    // Solve for 'margin-top'
    marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue +
                                          marginAfterAlias);
  } else if (marginAfter.isAuto()) {
    marginBeforeAlias =
        valueForLength(marginBefore, containerRelativeLogicalWidth);
    logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
    logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);

    // Solve for 'margin-bottom'
    marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue +
                                         marginBeforeAlias);
  } else {
    // Nothing is 'auto', just calculate the values.
    marginBeforeAlias =
        valueForLength(marginBefore, containerRelativeLogicalWidth);
    marginAfterAlias =
        valueForLength(marginAfter, containerRelativeLogicalWidth);
    logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
    // NOTE: It is not necessary to solve for 'bottom' because we don't ever
    // use the value.
  }

  // ---------------------------------------------------------------------------
  // 6. If at this point the values are over-constrained, ignore the value for
  //    'bottom' and solve for that value.
  // ---------------------------------------------------------------------------
  // NOTE: It is not necessary to do this step because we don't end up using the
  // value of 'bottom' regardless of whether the values are over-constrained or
  // not.

  // Use computed values to calculate the vertical position.
  LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias;
  computeLogicalTopPositionedOffset(logicalTopPos, this,
                                    computedValues.m_extent, containerBlock,
                                    containerLogicalHeight);
  computedValues.m_position = logicalTopPos;
}

LayoutRect LayoutReplaced::computeObjectFit(
    const LayoutSize* overriddenIntrinsicSize) const {
  LayoutRect contentRect = contentBoxRect();
  ObjectFit objectFit = style()->getObjectFit();

  if (objectFit == ObjectFitFill &&
      style()->objectPosition() == ComputedStyle::initialObjectPosition()) {
    return contentRect;
  }

  // TODO(davve): intrinsicSize doubles as both intrinsic size and intrinsic
  // ratio. In the case of SVG images this isn't correct since they can have
  // intrinsic ratio but no intrinsic size. In order to maintain aspect ratio,
  // the intrinsic size for SVG might be faked from the aspect ratio,
  // see SVGImage::containerSize().
  LayoutSize intrinsicSize = overriddenIntrinsicSize ? *overriddenIntrinsicSize
                                                     : this->intrinsicSize();
  if (!intrinsicSize.width() || !intrinsicSize.height())
    return contentRect;

  LayoutRect finalRect = contentRect;
  switch (objectFit) {
    case ObjectFitContain:
    case ObjectFitScaleDown:
    case ObjectFitCover:
      finalRect.setSize(finalRect.size().fitToAspectRatio(
          intrinsicSize, objectFit == ObjectFitCover ? AspectRatioFitGrow
                                                     : AspectRatioFitShrink));
      if (objectFit != ObjectFitScaleDown ||
          finalRect.width() <= intrinsicSize.width())
        break;
    // fall through
    case ObjectFitNone:
      finalRect.setSize(intrinsicSize);
      break;
    case ObjectFitFill:
      break;
    default:
      ASSERT_NOT_REACHED();
  }

  LayoutUnit xOffset = minimumValueForLength(
      style()->objectPosition().x(), contentRect.width() - finalRect.width());
  LayoutUnit yOffset = minimumValueForLength(
      style()->objectPosition().y(), contentRect.height() - finalRect.height());
  finalRect.move(xOffset, yOffset);

  return finalRect;
}

LayoutRect LayoutReplaced::replacedContentRect() const {
  return computeObjectFit();
}

void LayoutReplaced::computeIntrinsicSizingInfo(
    IntrinsicSizingInfo& intrinsicSizingInfo) const {
  // If there's an embeddedReplacedContent() of a remote, referenced document
  // available, this code-path should never be used.
  ASSERT(!embeddedReplacedContent());
  intrinsicSizingInfo.size = FloatSize(intrinsicLogicalWidth().toFloat(),
                                       intrinsicLogicalHeight().toFloat());

  // Figure out if we need to compute an intrinsic ratio.
  if (intrinsicSizingInfo.size.isEmpty() || !layoutObjectHasAspectRatio(this))
    return;

  intrinsicSizingInfo.aspectRatio = intrinsicSizingInfo.size;
}

static inline LayoutUnit resolveWidthForRatio(LayoutUnit height,
                                              const FloatSize& aspectRatio) {
  return LayoutUnit(height * aspectRatio.width() / aspectRatio.height());
}

static inline LayoutUnit resolveHeightForRatio(LayoutUnit width,
                                               const FloatSize& aspectRatio) {
  return LayoutUnit(width * aspectRatio.height() / aspectRatio.width());
}

LayoutUnit LayoutReplaced::computeConstrainedLogicalWidth(
    ShouldComputePreferred shouldComputePreferred) const {
  if (shouldComputePreferred == ComputePreferred)
    return computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit(),
                                                            ComputePreferred);
  // The aforementioned 'constraint equation' used for block-level, non-replaced
  // elements in normal flow:
  // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' +
  // 'padding-right' + 'border-right-width' + 'margin-right' = width of
  // containing block
  LayoutUnit logicalWidth = containingBlock()->availableLogicalWidth();

  // This solves above equation for 'width' (== logicalWidth).
  LayoutUnit marginStart =
      minimumValueForLength(style()->marginStart(), logicalWidth);
  LayoutUnit marginEnd =
      minimumValueForLength(style()->marginEnd(), logicalWidth);
  logicalWidth = (logicalWidth -
                  (marginStart + marginEnd + (size().width() - clientWidth())))
                     .clampNegativeToZero();
  return computeReplacedLogicalWidthRespectingMinMaxWidth(
      logicalWidth, shouldComputePreferred);
}

LayoutUnit LayoutReplaced::computeReplacedLogicalWidth(
    ShouldComputePreferred shouldComputePreferred) const {
  if (style()->logicalWidth().isSpecified() ||
      style()->logicalWidth().isIntrinsic())
    return computeReplacedLogicalWidthRespectingMinMaxWidth(
        computeReplacedLogicalWidthUsing(MainOrPreferredSize,
                                         style()->logicalWidth()),
        shouldComputePreferred);

  LayoutReplaced* contentLayoutObject = embeddedReplacedContent();

  // 10.3.2 Inline, replaced elements:
  // http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width
  IntrinsicSizingInfo intrinsicSizingInfo;
  computeIntrinsicSizingInfoForReplacedContent(contentLayoutObject,
                                               intrinsicSizingInfo);
  FloatSize constrainedSize =
      constrainIntrinsicSizeToMinMax(intrinsicSizingInfo);

  if (style()->logicalWidth().isAuto()) {
    bool computedHeightIsAuto = style()->logicalHeight().isAuto();

    // If 'height' and 'width' both have computed values of 'auto' and the
    // element also has an intrinsic width, then that intrinsic width is the
    // used value of 'width'.
    if (computedHeightIsAuto && intrinsicSizingInfo.hasWidth)
      return computeReplacedLogicalWidthRespectingMinMaxWidth(
          LayoutUnit(constrainedSize.width()), shouldComputePreferred);

    if (!intrinsicSizingInfo.aspectRatio.isEmpty()) {
      // If 'height' and 'width' both have computed values of 'auto' and the
      // element has no intrinsic width, but does have an intrinsic height and
      // intrinsic ratio; or if 'width' has a computed value of 'auto', 'height'
      // has some other computed value, and the element does have an intrinsic
      // ratio; then the used value of 'width' is: (used height) * (intrinsic
      // ratio).
      if ((computedHeightIsAuto && !intrinsicSizingInfo.hasWidth &&
           intrinsicSizingInfo.hasHeight) ||
          !computedHeightIsAuto) {
        LayoutUnit estimatedUsedWidth =
            intrinsicSizingInfo.hasWidth
                ? LayoutUnit(constrainedSize.width())
                : computeConstrainedLogicalWidth(shouldComputePreferred);
        LayoutUnit logicalHeight =
            computeReplacedLogicalHeight(estimatedUsedWidth);
        return computeReplacedLogicalWidthRespectingMinMaxWidth(
            resolveWidthForRatio(logicalHeight,
                                 intrinsicSizingInfo.aspectRatio),
            shouldComputePreferred);
      }

      // If 'height' and 'width' both have computed values of 'auto' and the
      // element has an intrinsic ratio but no intrinsic height or width, then
      // the used value of 'width' is undefined in CSS 2.1. However, it is
      // suggested that, if the containing block's width does not itself depend
      // on the replaced element's width, then the used value of 'width' is
      // calculated from the constraint equation used for block-level,
      // non-replaced elements in normal flow.
      if (computedHeightIsAuto && !intrinsicSizingInfo.hasWidth &&
          !intrinsicSizingInfo.hasHeight)
        return computeConstrainedLogicalWidth(shouldComputePreferred);
    }

    // Otherwise, if 'width' has a computed value of 'auto', and the element has
    // an intrinsic width, then that intrinsic width is the used value of
    // 'width'.
    if (intrinsicSizingInfo.hasWidth)
      return computeReplacedLogicalWidthRespectingMinMaxWidth(
          LayoutUnit(constrainedSize.width()), shouldComputePreferred);

    // Otherwise, if 'width' has a computed value of 'auto', but none of the
    // conditions above are met, then the used value of 'width' becomes 300px.
    // If 300px is too wide to fit the device, UAs should use the width of the
    // largest rectangle that has a 2:1 ratio and fits the device instead.
    // Note: We fall through and instead return intrinsicLogicalWidth() here -
    // to preserve existing WebKit behavior, which might or might not be
    // correct, or desired.
    // Changing this to return cDefaultWidth, will affect lots of test results.
    // Eg. some tests assume that a blank <img> tag (which implies
    // width/height=auto) has no intrinsic size, which is wrong per CSS 2.1, but
    // matches our behavior since a long time.
  }

  return computeReplacedLogicalWidthRespectingMinMaxWidth(
      intrinsicLogicalWidth(), shouldComputePreferred);
}

LayoutUnit LayoutReplaced::computeReplacedLogicalHeight(
    LayoutUnit estimatedUsedWidth) const {
  // 10.5 Content height: the 'height' property:
  // http://www.w3.org/TR/CSS21/visudet.html#propdef-height
  if (hasReplacedLogicalHeight())
    return computeReplacedLogicalHeightRespectingMinMaxHeight(
        computeReplacedLogicalHeightUsing(MainOrPreferredSize,
                                          style()->logicalHeight()));

  LayoutReplaced* contentLayoutObject = embeddedReplacedContent();

  // 10.6.2 Inline, replaced elements:
  // http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height
  IntrinsicSizingInfo intrinsicSizingInfo;
  computeIntrinsicSizingInfoForReplacedContent(contentLayoutObject,
                                               intrinsicSizingInfo);
  FloatSize constrainedSize =
      constrainIntrinsicSizeToMinMax(intrinsicSizingInfo);

  bool widthIsAuto = style()->logicalWidth().isAuto();

  // If 'height' and 'width' both have computed values of 'auto' and the element
  // also has an intrinsic height, then that intrinsic height is the used value
  // of 'height'.
  if (widthIsAuto && intrinsicSizingInfo.hasHeight)
    return computeReplacedLogicalHeightRespectingMinMaxHeight(
        LayoutUnit(constrainedSize.height()));

  // Otherwise, if 'height' has a computed value of 'auto', and the element has
  // an intrinsic ratio then the used value of 'height' is:
  // (used width) / (intrinsic ratio)
  if (!intrinsicSizingInfo.aspectRatio.isEmpty()) {
    LayoutUnit usedWidth =
        estimatedUsedWidth ? estimatedUsedWidth : availableLogicalWidth();
    return computeReplacedLogicalHeightRespectingMinMaxHeight(
        resolveHeightForRatio(usedWidth, intrinsicSizingInfo.aspectRatio));
  }

  // Otherwise, if 'height' has a computed value of 'auto', and the element has
  // an intrinsic height, then that intrinsic height is the used value of
  // 'height'.
  if (intrinsicSizingInfo.hasHeight)
    return computeReplacedLogicalHeightRespectingMinMaxHeight(
        LayoutUnit(constrainedSize.height()));

  // Otherwise, if 'height' has a computed value of 'auto', but none of the
  // conditions above are met, then the used value of 'height' must be set to
  // the height of the largest rectangle that has a 2:1 ratio, has a height not
  // greater than 150px, and has a width not greater than the device width.
  return computeReplacedLogicalHeightRespectingMinMaxHeight(
      intrinsicLogicalHeight());
}

void LayoutReplaced::computeIntrinsicLogicalWidths(
    LayoutUnit& minLogicalWidth,
    LayoutUnit& maxLogicalWidth) const {
  minLogicalWidth = maxLogicalWidth = intrinsicLogicalWidth();
}

void LayoutReplaced::computePreferredLogicalWidths() {
  ASSERT(preferredLogicalWidthsDirty());

  // We cannot resolve some logical width here (i.e. percent, fill-available or
  // fit-content) as the available logical width may not be set on our
  // containing block.
  const Length& logicalWidth = style()->logicalWidth();
  if (logicalWidth.isPercentOrCalc() || logicalWidth.isFillAvailable() ||
      logicalWidth.isFitContent())
    computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth,
                                  m_maxPreferredLogicalWidth);
  else
    m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth =
        computeReplacedLogicalWidth(ComputePreferred);

  const ComputedStyle& styleToUse = styleRef();
  if (styleToUse.logicalWidth().isPercentOrCalc() ||
      styleToUse.logicalMaxWidth().isPercentOrCalc())
    m_minPreferredLogicalWidth = LayoutUnit();

  if (styleToUse.logicalMinWidth().isFixed() &&
      styleToUse.logicalMinWidth().value() > 0) {
    m_maxPreferredLogicalWidth = std::max(
        m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(
                                        styleToUse.logicalMinWidth().value()));
    m_minPreferredLogicalWidth = std::max(
        m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(
                                        styleToUse.logicalMinWidth().value()));
  }

  if (styleToUse.logicalMaxWidth().isFixed()) {
    m_maxPreferredLogicalWidth = std::min(
        m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(
                                        styleToUse.logicalMaxWidth().value()));
    m_minPreferredLogicalWidth = std::min(
        m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(
                                        styleToUse.logicalMaxWidth().value()));
  }

  LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
  m_minPreferredLogicalWidth += borderAndPadding;
  m_maxPreferredLogicalWidth += borderAndPadding;

  clearPreferredLogicalWidthsDirty();
}

PositionWithAffinity LayoutReplaced::positionForPoint(
    const LayoutPoint& point) {
  // FIXME: This code is buggy if the replaced element is relative positioned.
  InlineBox* box = inlineBoxWrapper();
  RootInlineBox* rootBox = box ? &box->root() : 0;

  LayoutUnit top = rootBox ? rootBox->selectionTop() : logicalTop();
  LayoutUnit bottom = rootBox ? rootBox->selectionBottom() : logicalBottom();

  LayoutUnit blockDirectionPosition = isHorizontalWritingMode()
                                          ? point.y() + location().y()
                                          : point.x() + location().x();
  LayoutUnit lineDirectionPosition = isHorizontalWritingMode()
                                         ? point.x() + location().x()
                                         : point.y() + location().y();

  if (blockDirectionPosition < top)
    return createPositionWithAffinity(
        caretMinOffset());  // coordinates are above

  if (blockDirectionPosition >= bottom)
    return createPositionWithAffinity(
        caretMaxOffset());  // coordinates are below

  if (node()) {
    if (lineDirectionPosition <= logicalLeft() + (logicalWidth() / 2))
      return createPositionWithAffinity(0);
    return createPositionWithAffinity(1);
  }

  return LayoutBox::positionForPoint(point);
}

LayoutRect LayoutReplaced::localSelectionRect() const {
  if (getSelectionState() == SelectionNone)
    return LayoutRect();

  if (!inlineBoxWrapper()) {
    // We're a block-level replaced element.  Just return our own dimensions.
    return LayoutRect(LayoutPoint(), size());
  }

  RootInlineBox& root = inlineBoxWrapper()->root();
  LayoutUnit newLogicalTop =
      root.block().style()->isFlippedBlocksWritingMode()
          ? inlineBoxWrapper()->logicalBottom() - root.selectionBottom()
          : root.selectionTop() - inlineBoxWrapper()->logicalTop();
  if (root.block().style()->isHorizontalWritingMode())
    return LayoutRect(LayoutUnit(), newLogicalTop, size().width(),
                      root.selectionHeight());
  return LayoutRect(newLogicalTop, LayoutUnit(), root.selectionHeight(),
                    size().height());
}

void LayoutReplaced::setSelectionState(SelectionState state) {
  // The selection state for our containing block hierarchy is updated by the
  // base class call.
  LayoutBox::setSelectionState(state);

  if (!inlineBoxWrapper())
    return;

  // We only include the space below the baseline in our layer's cached paint
  // invalidation rect if the image is selected. Since the selection state has
  // changed update the rect.
  if (hasLayer()) {
    LayoutRect rect = localVisualRect();
    PaintLayer::mapRectToPaintInvalidationBacking(
        *this, containerForPaintInvalidation(), rect);
    setPreviousVisualRect(rect);
  }

  if (canUpdateSelectionOnRootLineBoxes())
    inlineBoxWrapper()->root().setHasSelectedChildren(state != SelectionNone);
}

void LayoutReplaced::IntrinsicSizingInfo::transpose() {
  size = size.transposedSize();
  aspectRatio = aspectRatio.transposedSize();
  std::swap(hasWidth, hasHeight);
}

}  // namespace blink
