blob: 39876b96fcb4e7fe25ebe832e6867f2e1d5f8e94 [file] [log] [blame]
// Copyright 2015 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 "core/paint/RoundedInnerRectClipper.h"
#include "core/paint/PaintInfo.h"
#include "platform/graphics/paint/ClipDisplayItem.h"
#include "platform/graphics/paint/DisplayItemClient.h"
#include "platform/graphics/paint/PaintController.h"
namespace blink {
RoundedInnerRectClipper::RoundedInnerRectClipper(
const DisplayItemClient& display_item,
const PaintInfo& paint_info,
const LayoutRect& rect,
const FloatRoundedRect& clip_rect,
RoundedInnerRectClipperBehavior behavior)
: display_item_(display_item),
paint_info_(paint_info),
use_paint_controller_(behavior == kApplyToDisplayList),
clip_type_(use_paint_controller_
? paint_info_.DisplayItemTypeForClipping()
: DisplayItem::kClipBoxPaintPhaseFirst) {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() && use_paint_controller_)
return;
Vector<FloatRoundedRect> rounded_rect_clips;
if (clip_rect.IsRenderable()) {
rounded_rect_clips.push_back(clip_rect);
} else {
// We create a rounded rect for each of the corners and clip it, while
// making sure we clip opposing corners together.
if (!clip_rect.GetRadii().TopLeft().IsEmpty() ||
!clip_rect.GetRadii().BottomRight().IsEmpty()) {
FloatRect top_corner(clip_rect.Rect().X(), clip_rect.Rect().Y(),
rect.MaxX() - clip_rect.Rect().X(),
rect.MaxY() - clip_rect.Rect().Y());
FloatRoundedRect::Radii top_corner_radii;
top_corner_radii.SetTopLeft(clip_rect.GetRadii().TopLeft());
rounded_rect_clips.push_back(
FloatRoundedRect(top_corner, top_corner_radii));
FloatRect bottom_corner(rect.X().ToFloat(), rect.Y().ToFloat(),
clip_rect.Rect().MaxX() - rect.X().ToFloat(),
clip_rect.Rect().MaxY() - rect.Y().ToFloat());
FloatRoundedRect::Radii bottom_corner_radii;
bottom_corner_radii.SetBottomRight(clip_rect.GetRadii().BottomRight());
rounded_rect_clips.push_back(
FloatRoundedRect(bottom_corner, bottom_corner_radii));
}
if (!clip_rect.GetRadii().TopRight().IsEmpty() ||
!clip_rect.GetRadii().BottomLeft().IsEmpty()) {
FloatRect top_corner(rect.X().ToFloat(), clip_rect.Rect().Y(),
clip_rect.Rect().MaxX() - rect.X().ToFloat(),
rect.MaxY() - clip_rect.Rect().Y());
FloatRoundedRect::Radii top_corner_radii;
top_corner_radii.SetTopRight(clip_rect.GetRadii().TopRight());
rounded_rect_clips.push_back(
FloatRoundedRect(top_corner, top_corner_radii));
FloatRect bottom_corner(clip_rect.Rect().X(), rect.Y().ToFloat(),
rect.MaxX() - clip_rect.Rect().X(),
clip_rect.Rect().MaxY() - rect.Y().ToFloat());
FloatRoundedRect::Radii bottom_corner_radii;
bottom_corner_radii.SetBottomLeft(clip_rect.GetRadii().BottomLeft());
rounded_rect_clips.push_back(
FloatRoundedRect(bottom_corner, bottom_corner_radii));
}
}
if (use_paint_controller_) {
paint_info_.context.GetPaintController().CreateAndAppend<ClipDisplayItem>(
display_item, clip_type_, LayoutRect::InfiniteIntRect(),
rounded_rect_clips);
} else {
paint_info.context.Save();
for (const auto& rrect : rounded_rect_clips)
paint_info.context.ClipRoundedRect(rrect);
}
}
RoundedInnerRectClipper::~RoundedInnerRectClipper() {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() && use_paint_controller_)
return;
DisplayItem::Type end_type = DisplayItem::ClipTypeToEndClipType(clip_type_);
if (use_paint_controller_) {
paint_info_.context.GetPaintController().EndItem<EndClipDisplayItem>(
display_item_, end_type);
} else {
paint_info_.context.Restore();
}
}
} // namespace blink