blob: 520c388b6de03f0f44d7c85a06dcc52c6bcf5283 [file] [log] [blame]
// Copyright 2016 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_reflection_utils.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/paint/nine_piece_image_painter.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/geometry/length_functions.h"
#include "third_party/blink/renderer/platform/graphics/box_reflection.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
namespace blink {
BoxReflection BoxReflectionForPaintLayer(const PaintLayer& layer,
const ComputedStyle& style) {
const StyleReflection* reflect_style = style.BoxReflect();
LayoutRect frame_layout_rect =
ToLayoutBox(layer.GetLayoutObject()).FrameRect();
FloatRect frame_rect(frame_layout_rect);
BoxReflection::ReflectionDirection direction =
BoxReflection::kVerticalReflection;
float offset = 0;
switch (reflect_style->Direction()) {
case kReflectionAbove:
direction = BoxReflection::kVerticalReflection;
offset =
-FloatValueForLength(reflect_style->Offset(), frame_rect.Height());
break;
case kReflectionBelow:
direction = BoxReflection::kVerticalReflection;
offset =
2 * frame_rect.Height() +
FloatValueForLength(reflect_style->Offset(), frame_rect.Height());
break;
case kReflectionLeft:
direction = BoxReflection::kHorizontalReflection;
offset =
-FloatValueForLength(reflect_style->Offset(), frame_rect.Width());
break;
case kReflectionRight:
direction = BoxReflection::kHorizontalReflection;
offset = 2 * frame_rect.Width() +
FloatValueForLength(reflect_style->Offset(), frame_rect.Width());
break;
}
const NinePieceImage& mask_nine_piece = reflect_style->Mask();
if (!mask_nine_piece.HasImage())
return BoxReflection(direction, offset, nullptr, FloatRect());
LayoutRect mask_rect(LayoutPoint(), frame_layout_rect.Size());
LayoutRect mask_bounding_rect(mask_rect);
mask_bounding_rect.Expand(style.ImageOutsets(mask_nine_piece));
PaintRecordBuilder builder;
{
GraphicsContext& context = builder.Context();
DrawingRecorder recorder(context, layer.GetLayoutObject(),
DisplayItem::kReflectionMask);
Node* node = nullptr;
const LayoutObject* layout_object = &layer.GetLayoutObject();
for (; layout_object && !node; layout_object = layout_object->Parent())
node = layout_object->GeneratingNode();
NinePieceImagePainter::Paint(builder.Context(), layer.GetLayoutObject(),
layer.GetLayoutObject().GetDocument(), node,
mask_rect, style, mask_nine_piece);
}
return BoxReflection(direction, offset, builder.EndRecording(),
FloatRect(mask_bounding_rect));
}
} // namespace blink