1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/core/paint/fragment_data.h"
6 #include "third_party/blink/renderer/core/paint/paint_layer.h"
7 #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
8 
9 namespace blink {
10 
11 // These are defined here because of PaintLayer dependency.
12 
RareData()13 FragmentData::RareData::RareData() : unique_id(NewUniqueObjectId()) {}
14 
15 FragmentData::RareData::~RareData() = default;
16 
DestroyTail()17 void FragmentData::DestroyTail() {
18   if (!rare_data_)
19     return;
20   // Take next_fragment_ which clears it in this fragment.
21   std::unique_ptr<FragmentData> next = std::move(rare_data_->next_fragment_);
22   while (next && next->rare_data_) {
23     // Take next_fragment_ which clears it in that fragment, and the assignment
24     // deletes the previous |next|.
25     next = std::move(next->rare_data_->next_fragment_);
26   }
27   // The last |next| will be deleted on return.
28 }
29 
EnsureNextFragment()30 FragmentData& FragmentData::EnsureNextFragment() {
31   if (!NextFragment())
32     EnsureRareData().next_fragment_ = std::make_unique<FragmentData>();
33   return *rare_data_->next_fragment_;
34 }
35 
EnsureRareData()36 FragmentData::RareData& FragmentData::EnsureRareData() {
37   if (!rare_data_)
38     rare_data_ = std::make_unique<RareData>();
39   return *rare_data_;
40 }
41 
SetLayer(std::unique_ptr<PaintLayer> layer)42 void FragmentData::SetLayer(std::unique_ptr<PaintLayer> layer) {
43   if (rare_data_ || layer)
44     EnsureRareData().layer = std::move(layer);
45 }
46 
PreTransform() const47 const TransformPaintPropertyNode& FragmentData::PreTransform() const {
48   if (const auto* properties = PaintProperties()) {
49     if (const auto* transform = properties->Transform()) {
50       DCHECK(transform->Parent());
51       return *transform->Parent();
52     }
53   }
54   return LocalBorderBoxProperties().Transform();
55 }
56 
PostScrollTranslation() const57 const TransformPaintPropertyNode& FragmentData::PostScrollTranslation() const {
58   if (const auto* properties = PaintProperties()) {
59     if (properties->TransformIsolationNode())
60       return *properties->TransformIsolationNode();
61     if (properties->ScrollTranslation())
62       return *properties->ScrollTranslation();
63     if (properties->ReplacedContentTransform())
64       return *properties->ReplacedContentTransform();
65     if (properties->Perspective())
66       return *properties->Perspective();
67   }
68   return LocalBorderBoxProperties().Transform();
69 }
70 
PreClip() const71 const ClipPaintPropertyNode& FragmentData::PreClip() const {
72   if (const auto* properties = PaintProperties()) {
73     if (const auto* clip = properties->ClipPathClip()) {
74       // SPv1 composited clip-path has an alternative clip tree structure.
75       // If the clip-path is parented by the mask clip, it is only used
76       // to clip mask layer chunks, and not in the clip inheritance chain.
77       DCHECK(clip->Parent());
78       if (clip->Parent() != properties->MaskClip())
79         return *clip->Parent();
80     }
81     if (const auto* mask_clip = properties->MaskClip()) {
82       DCHECK(mask_clip->Parent());
83       return *mask_clip->Parent();
84     }
85     if (const auto* css_clip = properties->CssClip()) {
86       DCHECK(css_clip->Parent());
87       return *css_clip->Parent();
88     }
89   }
90   return LocalBorderBoxProperties().Clip();
91 }
92 
PostOverflowClip() const93 const ClipPaintPropertyNode& FragmentData::PostOverflowClip() const {
94   if (const auto* properties = PaintProperties()) {
95     if (properties->ClipIsolationNode())
96       return *properties->ClipIsolationNode();
97     if (properties->OverflowClip())
98       return *properties->OverflowClip();
99     if (properties->InnerBorderRadiusClip())
100       return *properties->InnerBorderRadiusClip();
101   }
102   return LocalBorderBoxProperties().Clip();
103 }
104 
PreEffect() const105 const EffectPaintPropertyNode& FragmentData::PreEffect() const {
106   if (const auto* properties = PaintProperties()) {
107     if (const auto* effect = properties->Effect()) {
108       DCHECK(effect->Parent());
109       return *effect->Parent();
110     }
111     if (const auto* filter = properties->Filter()) {
112       DCHECK(filter->Parent());
113       return *filter->Parent();
114     }
115   }
116   return LocalBorderBoxProperties().Effect();
117 }
118 
PreFilter() const119 const EffectPaintPropertyNode& FragmentData::PreFilter() const {
120   if (const auto* properties = PaintProperties()) {
121     if (const auto* filter = properties->Filter()) {
122       DCHECK(filter->Parent());
123       return *filter->Parent();
124     }
125   }
126   return LocalBorderBoxProperties().Effect();
127 }
128 
PostIsolationEffect() const129 const EffectPaintPropertyNode& FragmentData::PostIsolationEffect() const {
130   if (const auto* properties = PaintProperties()) {
131     if (properties->EffectIsolationNode())
132       return *properties->EffectIsolationNode();
133   }
134   return LocalBorderBoxProperties().Effect();
135 }
136 
InvalidateClipPathCache()137 void FragmentData::InvalidateClipPathCache() {
138   if (!rare_data_)
139     return;
140 
141   rare_data_->is_clip_path_cache_valid = false;
142   rare_data_->clip_path_bounding_box = base::nullopt;
143   rare_data_->clip_path_path = nullptr;
144 }
145 
SetClipPathCache(const IntRect & bounding_box,scoped_refptr<const RefCountedPath> path)146 void FragmentData::SetClipPathCache(const IntRect& bounding_box,
147                                     scoped_refptr<const RefCountedPath> path) {
148   EnsureRareData().is_clip_path_cache_valid = true;
149   rare_data_->clip_path_bounding_box = bounding_box;
150   rare_data_->clip_path_path = std::move(path);
151 }
152 
MapRectToFragment(const FragmentData & fragment,IntRect & rect) const153 void FragmentData::MapRectToFragment(const FragmentData& fragment,
154                                      IntRect& rect) const {
155   if (this == &fragment)
156     return;
157   const auto& from_transform = LocalBorderBoxProperties().Transform();
158   const auto& to_transform = fragment.LocalBorderBoxProperties().Transform();
159   rect.MoveBy(RoundedIntPoint(PaintOffset()));
160   GeometryMapper::SourceToDestinationRect(from_transform, to_transform, rect);
161   rect.MoveBy(-RoundedIntPoint(fragment.PaintOffset()));
162 }
163 
164 }  // namespace blink
165