1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
4  * All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
24 
25 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
26 #include "third_party/blink/renderer/core/animation/css/css_animations.h"
27 #include "third_party/blink/renderer/core/css/css_light_dark_value_pair.h"
28 #include "third_party/blink/renderer/core/css/css_property_value_set.h"
29 #include "third_party/blink/renderer/core/dom/node.h"
30 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
31 #include "third_party/blink/renderer/core/dom/pseudo_element.h"
32 #include "third_party/blink/renderer/core/style/computed_style.h"
33 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
34 
35 namespace blink {
36 
StyleResolverState(Document & document,Element & element,PseudoElement * pseudo_element,PseudoElementStyleRequest::RequestType pseudo_request_type,ElementType element_type,const ComputedStyle * parent_style,const ComputedStyle * layout_parent_style)37 StyleResolverState::StyleResolverState(
38     Document& document,
39     Element& element,
40     PseudoElement* pseudo_element,
41     PseudoElementStyleRequest::RequestType pseudo_request_type,
42     ElementType element_type,
43     const ComputedStyle* parent_style,
44     const ComputedStyle* layout_parent_style)
45     : element_context_(element),
46       document_(&document),
47       parent_style_(parent_style),
48       layout_parent_style_(layout_parent_style),
49       pseudo_request_type_(pseudo_request_type),
50       font_builder_(&document),
51       element_style_resources_(GetElement(),
52                                document.DevicePixelRatio(),
53                                pseudo_element),
54       pseudo_element_(pseudo_element),
55       element_type_(element_type) {
56   DCHECK(!!parent_style_ == !!layout_parent_style_);
57 
58   if (!parent_style_) {
59     parent_style_ = element_context_.ParentStyle();
60   }
61 
62   if (!layout_parent_style_)
63     layout_parent_style_ = element_context_.LayoutParentStyle();
64 
65   if (!layout_parent_style_)
66     layout_parent_style_ = parent_style_;
67 
68   DCHECK(document.IsActive());
69 }
70 
StyleResolverState(Document & document,Element & element,const ComputedStyle * parent_style,const ComputedStyle * layout_parent_style)71 StyleResolverState::StyleResolverState(Document& document,
72                                        Element& element,
73                                        const ComputedStyle* parent_style,
74                                        const ComputedStyle* layout_parent_style)
75     : StyleResolverState(document,
76                          element,
77                          nullptr /* pseudo_element */,
78                          PseudoElementStyleRequest::kForRenderer,
79                          ElementType::kElement,
80                          parent_style,
81                          layout_parent_style) {}
82 
StyleResolverState(Document & document,Element & element,PseudoId pseudo_id,PseudoElementStyleRequest::RequestType pseudo_request_type,const ComputedStyle * parent_style,const ComputedStyle * layout_parent_style)83 StyleResolverState::StyleResolverState(
84     Document& document,
85     Element& element,
86     PseudoId pseudo_id,
87     PseudoElementStyleRequest::RequestType pseudo_request_type,
88     const ComputedStyle* parent_style,
89     const ComputedStyle* layout_parent_style)
90     : StyleResolverState(document,
91                          element,
92                          element.GetPseudoElement(pseudo_id),
93                          pseudo_request_type,
94                          ElementType::kPseudoElement,
95                          parent_style,
96                          layout_parent_style) {}
97 
~StyleResolverState()98 StyleResolverState::~StyleResolverState() {
99   // For performance reasons, explicitly clear HeapVectors and
100   // HeapHashMaps to avoid giving a pressure on Oilpan's GC.
101   animation_update_.Clear();
102 }
103 
GetTreeScope() const104 TreeScope& StyleResolverState::GetTreeScope() const {
105   return GetElement().GetTreeScope();
106 }
107 
SetStyle(scoped_refptr<ComputedStyle> style)108 void StyleResolverState::SetStyle(scoped_refptr<ComputedStyle> style) {
109   // FIXME: Improve RAII of StyleResolverState to remove this function.
110   style_ = std::move(style);
111   css_to_length_conversion_data_ = CSSToLengthConversionData(
112       style_.get(), RootElementStyle(), GetDocument().GetLayoutView(),
113       style_->EffectiveZoom());
114 }
115 
TakeStyle()116 scoped_refptr<ComputedStyle> StyleResolverState::TakeStyle() {
117   return std::move(style_);
118 }
119 
UnzoomedLengthConversionData(const ComputedStyle * font_style) const120 CSSToLengthConversionData StyleResolverState::UnzoomedLengthConversionData(
121     const ComputedStyle* font_style) const {
122   float em = font_style->SpecifiedFontSize();
123   float rem = RootElementStyle() ? RootElementStyle()->SpecifiedFontSize() : 1;
124   CSSToLengthConversionData::FontSizes font_sizes(
125       em, rem, &font_style->GetFont(), font_style->EffectiveZoom());
126   CSSToLengthConversionData::ViewportSize viewport_size(
127       GetDocument().GetLayoutView());
128 
129   return CSSToLengthConversionData(Style(), font_sizes, viewport_size, 1);
130 }
131 
FontSizeConversionData() const132 CSSToLengthConversionData StyleResolverState::FontSizeConversionData() const {
133   return UnzoomedLengthConversionData(ParentStyle());
134 }
135 
UnzoomedLengthConversionData() const136 CSSToLengthConversionData StyleResolverState::UnzoomedLengthConversionData()
137     const {
138   return UnzoomedLengthConversionData(Style());
139 }
140 
SetParentStyle(scoped_refptr<const ComputedStyle> parent_style)141 void StyleResolverState::SetParentStyle(
142     scoped_refptr<const ComputedStyle> parent_style) {
143   parent_style_ = std::move(parent_style);
144 }
145 
SetLayoutParentStyle(scoped_refptr<const ComputedStyle> parent_style)146 void StyleResolverState::SetLayoutParentStyle(
147     scoped_refptr<const ComputedStyle> parent_style) {
148   layout_parent_style_ = std::move(parent_style);
149 }
150 
LoadPendingResources()151 void StyleResolverState::LoadPendingResources() {
152   if (pseudo_request_type_ == PseudoElementStyleRequest::kForComputedStyle ||
153       (ParentStyle() && ParentStyle()->IsEnsuredInDisplayNone()) ||
154       StyleRef().Display() == EDisplay::kNone ||
155       StyleRef().IsEnsuredOutsideFlatTree())
156     return;
157 
158   if (StyleRef().StyleType() == kPseudoIdTargetText) {
159     // Do not load any resources for ::target-text since that could leak text
160     // content to external stylesheets.
161     return;
162   }
163 
164   element_style_resources_.LoadPendingResources(StyleRef());
165 }
166 
ParentFontDescription() const167 const FontDescription& StyleResolverState::ParentFontDescription() const {
168   return parent_style_->GetFontDescription();
169 }
170 
SetZoom(float f)171 void StyleResolverState::SetZoom(float f) {
172   float parent_effective_zoom = ParentStyle()
173                                     ? ParentStyle()->EffectiveZoom()
174                                     : ComputedStyleInitialValues::InitialZoom();
175 
176   style_->SetZoom(f);
177 
178   if (f != 1.f)
179     GetDocument().CountUse(WebFeature::kCascadedCSSZoomNotEqualToOne);
180 
181   if (style_->SetEffectiveZoom(parent_effective_zoom * f))
182     font_builder_.DidChangeEffectiveZoom();
183 }
184 
SetEffectiveZoom(float f)185 void StyleResolverState::SetEffectiveZoom(float f) {
186   if (style_->SetEffectiveZoom(f))
187     font_builder_.DidChangeEffectiveZoom();
188 }
189 
SetWritingMode(WritingMode new_writing_mode)190 void StyleResolverState::SetWritingMode(WritingMode new_writing_mode) {
191   if (style_->GetWritingMode() == new_writing_mode) {
192     return;
193   }
194   style_->SetWritingMode(new_writing_mode);
195   font_builder_.DidChangeWritingMode();
196 }
197 
SetTextOrientation(ETextOrientation text_orientation)198 void StyleResolverState::SetTextOrientation(ETextOrientation text_orientation) {
199   if (style_->GetTextOrientation() != text_orientation) {
200     style_->SetTextOrientation(text_orientation);
201     font_builder_.DidChangeTextOrientation();
202   }
203 }
204 
GetParserMode() const205 CSSParserMode StyleResolverState::GetParserMode() const {
206   return GetDocument().InQuirksMode() ? kHTMLQuirksMode : kHTMLStandardMode;
207 }
208 
GetAnimatingElement() const209 Element* StyleResolverState::GetAnimatingElement() const {
210   if (element_type_ == ElementType::kElement)
211     return &GetElement();
212   DCHECK_EQ(ElementType::kPseudoElement, element_type_);
213   return pseudo_element_;
214 }
215 
ResolveLightDarkPair(const CSSProperty & property,const CSSValue & value)216 const CSSValue& StyleResolverState::ResolveLightDarkPair(
217     const CSSProperty& property,
218     const CSSValue& value) {
219   if (const auto* pair = DynamicTo<CSSLightDarkValuePair>(value)) {
220     if (!property.IsInherited())
221       Style()->SetHasNonInheritedLightDarkValue();
222     if (Style()->UsedColorScheme() == mojom::blink::ColorScheme::kLight)
223       return pair->First();
224     return pair->Second();
225   }
226   return value;
227 }
228 
MarkDependency(const CSSProperty & property)229 void StyleResolverState::MarkDependency(const CSSProperty& property) {
230   if (!RuntimeEnabledFeatures::CSSMatchedPropertiesCacheDependenciesEnabled())
231     return;
232   if (!HasValidDependencies())
233     return;
234 
235   has_incomparable_dependency_ |= !property.IsComputedValueComparable();
236   dependencies_.insert(property.GetCSSPropertyName());
237 }
238 
239 }  // namespace blink
240