blob: 4e102ef12fc6219e5f9b4768a81526dd97ffc85a [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PAINT_PROPERTY_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PAINT_PROPERTY_NODE_H_
#include <algorithm>
#include <optional>
#include "base/check_op.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h"
#include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_property_node.h"
#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
#include "third_party/blink/renderer/platform/graphics/path.h"
#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
class EffectPaintPropertyNode;
class GeometryMapperClipCache;
class PropertyTreeState;
// A clip rect created by a css property such as "overflow" or "clip".
// Along with a reference to the transform space the clip rect is based on,
// and a parent ClipPaintPropertyNode for inherited clips.
//
// The clip tree is rooted at a node with no parent. This root node should
// not be modified.
class ClipPaintPropertyNode;
class PLATFORM_EXPORT ClipPaintPropertyNodeOrAlias
: public PaintPropertyNodeBase<ClipPaintPropertyNodeOrAlias,
ClipPaintPropertyNode> {
public:
// Checks if the accumulated clip from |this| to |relative_to_state.Clip()|
// has changed, at least significance of |change|, in the space of
// |relative_to_state.Transform()|. We check for changes of not only clip
// nodes, but also LocalTransformSpace relative to |relative_to_state
// .Transform()| of the clip nodes. |transform_not_to_check| specifies a
// transform node that the caller has checked or will check its change in
// other ways and this function should treat it as unchanged.
bool Changed(
PaintPropertyChangeType change,
const PropertyTreeState& relative_to_state,
const TransformPaintPropertyNodeOrAlias* transform_not_to_check) const;
// See PaintPropertyNode::ChangedSequenceNumber().
void ClearChangedToRoot(int sequence_number) const;
void AddChanged(PaintPropertyChangeType changed) final {
DCHECK_NE(PaintPropertyChangeType::kUnchanged, changed);
GeometryMapperClipCache::ClearCache();
PaintPropertyNodeBase::AddChanged(changed);
}
protected:
using PaintPropertyNodeBase::PaintPropertyNodeBase;
};
class ClipPaintPropertyNodeAlias final : public ClipPaintPropertyNodeOrAlias {
public:
static scoped_refptr<ClipPaintPropertyNodeAlias> Create(
const ClipPaintPropertyNodeOrAlias& parent) {
return base::AdoptRef(new ClipPaintPropertyNodeAlias(parent));
}
private:
explicit ClipPaintPropertyNodeAlias(
const ClipPaintPropertyNodeOrAlias& parent)
: ClipPaintPropertyNodeOrAlias(parent, kParentAlias) {}
};
class PLATFORM_EXPORT ClipPaintPropertyNode final
: public ClipPaintPropertyNodeOrAlias {
public:
// To make it less verbose and more readable to construct and update a node,
// a struct with default values is used to represent the state.
struct PLATFORM_EXPORT State {
DISALLOW_NEW();
public:
State(scoped_refptr<const TransformPaintPropertyNodeOrAlias>
local_transform_space,
const gfx::RectF& layout_clip_rect,
const FloatRoundedRect& paint_clip_rect)
: local_transform_space(std::move(local_transform_space)) {
SetClipRect(layout_clip_rect, paint_clip_rect);
}
State(scoped_refptr<const TransformPaintPropertyNodeOrAlias>
local_transform_space,
scoped_refptr<const EffectPaintPropertyNode> pixel_moving_filter)
: local_transform_space(std::move(local_transform_space)),
pixel_moving_filter(std::move(pixel_moving_filter)) {
DCHECK(layout_clip_rect_.IsInfinite());
paint_clip_rect_ = FloatRoundedRect(layout_clip_rect_.Rect());
}
scoped_refptr<const TransformPaintPropertyNodeOrAlias>
local_transform_space;
std::optional<FloatClipRect> layout_clip_rect_excluding_overlay_scrollbars;
std::optional<Path> clip_path;
// If this is not nullptr, this clip node will generate a cc clip node to
// expand clip rect for a pixel-moving filter.
scoped_refptr<const EffectPaintPropertyNode> pixel_moving_filter;
void SetClipRect(const gfx::RectF& layout_clip_rect_arg,
const FloatRoundedRect& paint_clip_rect_arg) {
layout_clip_rect_.SetRect(layout_clip_rect_arg);
if (paint_clip_rect_arg.IsRounded())
layout_clip_rect_.SetHasRadius();
paint_clip_rect_ = paint_clip_rect_arg;
}
PaintPropertyChangeType ComputeChange(const State& other) const;
bool ClipPathEquals(const std::optional<Path>& p) const {
return (!clip_path && !p) || (clip_path && p && *clip_path == *p);
}
private:
friend class ClipPaintPropertyNode;
FloatClipRect layout_clip_rect_;
FloatRoundedRect paint_clip_rect_;
};
// This node is really a sentinel, and does not represent a real clip space.
static const ClipPaintPropertyNode& Root();
static scoped_refptr<ClipPaintPropertyNode> Create(
const ClipPaintPropertyNodeOrAlias& parent,
State&& state) {
return base::AdoptRef(new ClipPaintPropertyNode(&parent, std::move(state)));
}
// The empty AnimationState struct is to meet the requirement of
// ObjectPaintProperties.
struct AnimationState {
STACK_ALLOCATED();
};
PaintPropertyChangeType Update(const ClipPaintPropertyNodeOrAlias& parent,
State&& state,
const AnimationState& = AnimationState()) {
auto parent_changed = SetParent(parent);
auto state_changed = state_.ComputeChange(state);
if (state_changed != PaintPropertyChangeType::kUnchanged) {
state_ = std::move(state);
AddChanged(state_changed);
}
return std::max(parent_changed, state_changed);
}
const ClipPaintPropertyNode& Unalias() const = delete;
bool IsParentAlias() const = delete;
const TransformPaintPropertyNodeOrAlias& LocalTransformSpace() const {
return *state_.local_transform_space;
}
// The clip rect for painting and compositing. It may be pixel snapped, or
// not (e.g. for SVG).
const FloatRoundedRect& PaintClipRect() const {
return state_.paint_clip_rect_;
}
// The clip rect used for GeometryMapper to map in layout coordinates.
const FloatClipRect& LayoutClipRect() const {
return state_.layout_clip_rect_;
}
const FloatClipRect& LayoutClipRectExcludingOverlayScrollbars() const {
return state_.layout_clip_rect_excluding_overlay_scrollbars
? *state_.layout_clip_rect_excluding_overlay_scrollbars
: state_.layout_clip_rect_;
}
const std::optional<Path>& ClipPath() const { return state_.clip_path; }
bool ClipPathEquals(const std::optional<Path>& p) const {
return state_.ClipPathEquals(p);
}
const EffectPaintPropertyNode* PixelMovingFilter() const {
return state_.pixel_moving_filter.get();
}
const ClipPaintPropertyNode* NearestPixelMovingFilterClip() const {
return GetClipCache().NearestPixelMovingFilterClip();
}
std::unique_ptr<JSONObject> ToJSON() const final;
private:
ClipPaintPropertyNode(const ClipPaintPropertyNodeOrAlias* parent,
State&& state)
: ClipPaintPropertyNodeOrAlias(parent), state_(std::move(state)) {}
// For access to GetClipCache();
friend class GeometryMapper;
friend class GeometryMapperClipCache;
friend class GeometryMapperTest;
GeometryMapperClipCache& GetClipCache() const {
if (!clip_cache_)
clip_cache_ = std::make_unique<GeometryMapperClipCache>();
clip_cache_->UpdateIfNeeded(*this);
return *clip_cache_;
}
State state_;
mutable std::unique_ptr<GeometryMapperClipCache> clip_cache_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PAINT_PROPERTY_NODE_H_