// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/paint/box_model_object_painter.h"

#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/line/root_inline_box.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect_outsets.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"

namespace blink {

namespace {

Node* GeneratingNodeForObject(const LayoutBoxModelObject& box_model) {
  Node* node = nullptr;
  const LayoutObject* layout_object = &box_model;
  for (; layout_object && !node; layout_object = layout_object->Parent()) {
    node = layout_object->GeneratingNode();
  }
  return node;
}

LayoutSize LogicalOffsetOnLine(const InlineFlowBox& flow_box) {
  // Compute the offset of the passed flow box when seen as part of an
  // unbroken continuous strip (c.f box-decoration-break: slice.)
  LayoutUnit logical_offset_on_line;
  if (flow_box.IsLeftToRightDirection()) {
    for (const InlineFlowBox* curr = flow_box.PrevForSameLayoutObject(); curr;
         curr = curr->PrevForSameLayoutObject())
      logical_offset_on_line += curr->LogicalWidth();
  } else {
    for (const InlineFlowBox* curr = flow_box.NextForSameLayoutObject(); curr;
         curr = curr->NextForSameLayoutObject())
      logical_offset_on_line += curr->LogicalWidth();
  }
  LayoutSize logical_offset(logical_offset_on_line, LayoutUnit());
  return flow_box.IsHorizontal() ? logical_offset
                                 : logical_offset.TransposedSize();
}

}  // anonymous namespace

BoxModelObjectPainter::BoxModelObjectPainter(const LayoutBoxModelObject& box,
                                             const InlineFlowBox* flow_box)
    : BoxPainterBase(&box.GetDocument(),
                     box.StyleRef(),
                     GeneratingNodeForObject(box)),
      box_model_(box),
      flow_box_(flow_box) {}

bool BoxModelObjectPainter::IsPaintingScrollingBackground(
    const LayoutBoxModelObject* box_model_,
    const PaintInfo& paint_info) {
  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
    // TODO(wangxianzhu): For CAP, remove this method and let callers use
    // PaintInfo::IsPaintScrollingBackground() directly.
    return paint_info.IsPaintingScrollingBackground();
  }
  return paint_info.PaintFlags() & kPaintLayerPaintingOverflowContents &&
         !(paint_info.PaintFlags() &
           kPaintLayerPaintingCompositingBackgroundPhase) &&
         box_model_ == paint_info.PaintContainer();
}

void BoxModelObjectPainter::PaintTextClipMask(GraphicsContext& context,
                                              const IntRect& mask_rect,
                                              const LayoutPoint& paint_offset,
                                              bool object_has_multiple_boxes) {
  PaintInfo paint_info(context, mask_rect, PaintPhase::kTextClip,
                       kGlobalPaintNormalPhase, 0);
  if (flow_box_) {
    LayoutSize local_offset = ToLayoutSize(flow_box_->Location());
    if (object_has_multiple_boxes &&
        box_model_.StyleRef().BoxDecorationBreak() ==
            EBoxDecorationBreak::kSlice) {
      local_offset -= LogicalOffsetOnLine(*flow_box_);
    }
    const RootInlineBox& root = flow_box_->Root();
    flow_box_->Paint(paint_info, paint_offset - local_offset, root.LineTop(),
                     root.LineBottom());
  } else if (box_model_.IsLayoutBlock()) {
    ToLayoutBlock(box_model_).PaintObject(paint_info, paint_offset);
  } else {
    // We should go through the above path for LayoutInlines.
    DCHECK(!box_model_.IsLayoutInline());
    // Other types of objects don't have anything meaningful to paint for text
    // clip mask.
  }
}

LayoutRect BoxModelObjectPainter::AdjustRectForScrolledContent(
    const PaintInfo& paint_info,
    const BoxPainterBase::FillLayerInfo& info,
    const LayoutRect& rect) {
  LayoutRect scrolled_paint_rect = rect;
  GraphicsContext& context = paint_info.context;
  if (info.is_clipped_with_local_scrolling &&
      !IsPaintingScrollingBackground(&box_model_, paint_info)) {
    // Clip to the overflow area.
    const LayoutBox& this_box = ToLayoutBox(box_model_);
    // TODO(chrishtr): this should be pixel-snapped.
    context.Clip(FloatRect(this_box.OverflowClipRect(rect.Location())));

    // Adjust the paint rect to reflect a scrolled content box with borders at
    // the ends.
    IntSize offset = this_box.ScrolledContentOffset();
    scrolled_paint_rect.Move(-offset);
    LayoutRectOutsets border = AdjustedBorderOutsets(info);
    scrolled_paint_rect.SetWidth(border.Left() + this_box.ScrollWidth() +
                                 border.Right());
    scrolled_paint_rect.SetHeight(this_box.BorderTop() +
                                  this_box.ScrollHeight() +
                                  this_box.BorderBottom());
  }
  return scrolled_paint_rect;
}

LayoutRectOutsets BoxModelObjectPainter::ComputeBorders() const {
  return box_model_.BorderBoxOutsets();
}

LayoutRectOutsets BoxModelObjectPainter::ComputePadding() const {
  return box_model_.PaddingOutsets();
}

BoxPainterBase::FillLayerInfo BoxModelObjectPainter::GetFillLayerInfo(
    const Color& color,
    const FillLayer& bg_layer,
    BackgroundBleedAvoidance bleed_avoidance) const {
  return BoxPainterBase::FillLayerInfo(
      box_model_.GetDocument(), box_model_.StyleRef(),
      box_model_.HasOverflowClip(), color, bg_layer, bleed_avoidance,
      (flow_box_ ? flow_box_->IncludeLogicalLeftEdge() : true),
      (flow_box_ ? flow_box_->IncludeLogicalRightEdge() : true));
}

}  // namespace blink
