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 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_STYLE_RESOLVER_STATE_H_
24 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_STYLE_RESOLVER_STATE_H_
25 
26 #include <memory>
27 #include "third_party/blink/renderer/core/animation/css/css_animation_update.h"
28 #include "third_party/blink/renderer/core/core_export.h"
29 #include "third_party/blink/renderer/core/css/css_property_name.h"
30 #include "third_party/blink/renderer/core/css/css_property_names.h"
31 #include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h"
32 #include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
33 #include "third_party/blink/renderer/core/css/pseudo_style_request.h"
34 #include "third_party/blink/renderer/core/css/resolver/css_to_style_map.h"
35 #include "third_party/blink/renderer/core/css/resolver/element_resolve_context.h"
36 #include "third_party/blink/renderer/core/css/resolver/element_style_resources.h"
37 #include "third_party/blink/renderer/core/css/resolver/font_builder.h"
38 #include "third_party/blink/renderer/core/dom/document.h"
39 #include "third_party/blink/renderer/core/dom/element.h"
40 
41 namespace blink {
42 
43 class ComputedStyle;
44 class FontDescription;
45 class PseudoElement;
46 
47 // A per-element object which wraps an ElementResolveContext. It collects state
48 // throughout the process of computing the style. It also gives convenient
49 // access to other element-related information.
50 class CORE_EXPORT StyleResolverState {
51   STACK_ALLOCATED();
52 
53   enum class ElementType { kElement, kPseudoElement };
54 
55  public:
56   StyleResolverState(Document&,
57                      Element&,
58                      const ComputedStyle* parent_style = nullptr,
59                      const ComputedStyle* layout_parent_style = nullptr);
60   StyleResolverState(Document&,
61                      Element&,
62                      PseudoId,
63                      PseudoElementStyleRequest::RequestType,
64                      const ComputedStyle* parent_style,
65                      const ComputedStyle* layout_parent_style);
66   StyleResolverState(const StyleResolverState&) = delete;
67   StyleResolverState& operator=(const StyleResolverState&) = delete;
68   ~StyleResolverState();
69 
IsForPseudoElement()70   bool IsForPseudoElement() const {
71     return element_type_ == ElementType::kPseudoElement;
72   }
73 
74   // In FontFaceSet and CanvasRenderingContext2D, we don't have an element to
75   // grab the document from.  This is why we have to store the document
76   // separately.
GetDocument()77   Document& GetDocument() const { return *document_; }
78   // These are all just pass-through methods to ElementResolveContext.
GetElement()79   Element& GetElement() const { return element_context_.GetElement(); }
80   TreeScope& GetTreeScope() const;
ParentNode()81   const ContainerNode* ParentNode() const {
82     return element_context_.ParentNode();
83   }
RootElementStyle()84   const ComputedStyle* RootElementStyle() const {
85     if (const auto* root_element_style = element_context_.RootElementStyle())
86       return root_element_style;
87     return Style();
88   }
ElementLinkState()89   EInsideLink ElementLinkState() const {
90     return element_context_.ElementLinkState();
91   }
DistributedToV0InsertionPoint()92   bool DistributedToV0InsertionPoint() const {
93     return element_context_.DistributedToV0InsertionPoint();
94   }
95 
ElementContext()96   const ElementResolveContext& ElementContext() const {
97     return element_context_;
98   }
99 
100   void SetStyle(scoped_refptr<ComputedStyle>);
Style()101   const ComputedStyle* Style() const { return style_.get(); }
Style()102   ComputedStyle* Style() { return style_.get(); }
StyleRef()103   ComputedStyle& StyleRef() {
104     DCHECK(style_);
105     return *style_;
106   }
107   scoped_refptr<ComputedStyle> TakeStyle();
108 
CssToLengthConversionData()109   const CSSToLengthConversionData& CssToLengthConversionData() const {
110     return css_to_length_conversion_data_;
111   }
112   CSSToLengthConversionData FontSizeConversionData() const;
113   CSSToLengthConversionData UnzoomedLengthConversionData() const;
114 
SetConversionFontSizes(const CSSToLengthConversionData::FontSizes & font_sizes)115   void SetConversionFontSizes(
116       const CSSToLengthConversionData::FontSizes& font_sizes) {
117     css_to_length_conversion_data_.SetFontSizes(font_sizes);
118   }
SetConversionZoom(float zoom)119   void SetConversionZoom(float zoom) {
120     css_to_length_conversion_data_.SetZoom(zoom);
121   }
122 
AnimationUpdate()123   CSSAnimationUpdate& AnimationUpdate() { return animation_update_; }
AnimationUpdate()124   const CSSAnimationUpdate& AnimationUpdate() const {
125     return animation_update_;
126   }
127 
IsAnimationInterpolationMapReady()128   bool IsAnimationInterpolationMapReady() const {
129     return is_animation_interpolation_map_ready_;
130   }
SetIsAnimationInterpolationMapReady()131   void SetIsAnimationInterpolationMapReady() {
132     is_animation_interpolation_map_ready_ = true;
133   }
134 
135   Element* GetAnimatingElement() const;
136 
137   void SetParentStyle(scoped_refptr<const ComputedStyle>);
ParentStyle()138   const ComputedStyle* ParentStyle() const { return parent_style_.get(); }
139 
140   void SetLayoutParentStyle(scoped_refptr<const ComputedStyle>);
LayoutParentStyle()141   const ComputedStyle* LayoutParentStyle() const {
142     return layout_parent_style_.get();
143   }
144 
GetElementStyleResources()145   ElementStyleResources& GetElementStyleResources() {
146     return element_style_resources_;
147   }
148 
149   void LoadPendingResources();
150 
151   // FIXME: Once styleImage can be made to not take a StyleResolverState
152   // this convenience function should be removed. As-is, without this, call
153   // sites are extremely verbose.
GetStyleImage(CSSPropertyID property_id,const CSSValue & value)154   StyleImage* GetStyleImage(CSSPropertyID property_id, const CSSValue& value) {
155     return element_style_resources_.GetStyleImage(property_id, value);
156   }
157 
GetFontBuilder()158   FontBuilder& GetFontBuilder() { return font_builder_; }
GetFontBuilder()159   const FontBuilder& GetFontBuilder() const { return font_builder_; }
160   // FIXME: These exist as a primitive way to track mutations to font-related
161   // properties on a ComputedStyle. As designed, these are very error-prone, as
162   // some callers set these directly on the ComputedStyle w/o telling us.
163   // Presumably we'll want to design a better wrapper around ComputedStyle for
164   // tracking these mutations and separate it from StyleResolverState.
165   const FontDescription& ParentFontDescription() const;
166 
167   void SetZoom(float);
168   void SetEffectiveZoom(float);
169   void SetWritingMode(WritingMode);
170   void SetTextOrientation(ETextOrientation);
171 
SetHasDirAutoAttribute(bool value)172   void SetHasDirAutoAttribute(bool value) { has_dir_auto_attribute_ = value; }
HasDirAutoAttribute()173   bool HasDirAutoAttribute() const { return has_dir_auto_attribute_; }
174 
175   CSSParserMode GetParserMode() const;
176 
177   // If the input CSSValue is a CSSLightDarkValuePair, return the light or dark
178   // CSSValue based on the UsedColorScheme. For all other values, just return a
179   // reference to the passed value. If the property is a non-inherited one, mark
180   // the ComputedStyle as having such a pair since that will make sure its not
181   // stored in the MatchedPropertiesCache.
182   const CSSValue& ResolveLightDarkPair(const CSSProperty&, const CSSValue&);
183 
184   // The dependencies we track here end up in an entry in the
185   // MatchedPropertiesCache. Declarations such as "all:inherit" incurs several
186   // hundred dependencies, which is too big to cache, hence the number of
187   // dependencies we can track is limited.
188   static const size_t kMaxDependencies = 8;
189 
190   // Mark the ComputedStyle as possibly dependent on the specified property.
191   //
192   // A "dependency" in this context means that one or more of the computed
193   // values held by the ComputedStyle depends on the computed value of the
194   // parent ComputedStyle.
195   //
196   // For example, a declaration such as background-color:var(--x) would incur
197   // a dependency on --x.
198   void MarkDependency(const CSSProperty&);
199 
200   // Returns the set of all properties seen by MarkDependency.
201   //
202   // The caller must check if the dependencies are valid via
203   // HasValidDependencies() before calling this function.
204   //
205   // Note that this set might be larger than the actual set of dependencies,
206   // as we do some degree of over-marking to keep the implementation simple.
207   //
208   // For example, we mark all custom properties referenced as dependencies, even
209   // though the ComputedStyle itself may define a value for some or all of those
210   // custom properties. In the following example, both --x and --y will be
211   // added to this set, even though only --y is a true dependency:
212   //
213   //  div {
214   //    --x: 10px;
215   //    margin: var(--x) (--y);
216   //  }
217   //
Dependencies()218   const HashSet<CSSPropertyName>& Dependencies() const {
219     DCHECK(HasValidDependencies());
220     return dependencies_;
221   }
222 
223   // True if there's a dependency without the kComputedValueComparable flag.
HasIncomparableDependency()224   bool HasIncomparableDependency() const {
225     return has_incomparable_dependency_;
226   }
227 
HasValidDependencies()228   bool HasValidDependencies() const {
229     return dependencies_.size() <= kMaxDependencies;
230   }
231 
SetCanCacheBaseStyle(bool state)232   void SetCanCacheBaseStyle(bool state) { can_cache_base_style_ = state; }
CanCacheBaseStyle()233   bool CanCacheBaseStyle() const { return can_cache_base_style_; }
234 
235  private:
236   StyleResolverState(Document&,
237                      Element&,
238                      PseudoElement*,
239                      PseudoElementStyleRequest::RequestType,
240                      ElementType,
241                      const ComputedStyle* parent_style,
242                      const ComputedStyle* layout_parent_style);
243 
244   CSSToLengthConversionData UnzoomedLengthConversionData(
245       const ComputedStyle* font_style) const;
246 
247   ElementResolveContext element_context_;
248   Document* document_;
249 
250   // style_ is the primary output for each element's style resolve.
251   scoped_refptr<ComputedStyle> style_;
252 
253   CSSToLengthConversionData css_to_length_conversion_data_;
254 
255   // parent_style_ is not always just ElementResolveContext::ParentStyle(),
256   // so we keep it separate.
257   scoped_refptr<const ComputedStyle> parent_style_;
258   // This will almost-always be the same that parent_style_, except in the
259   // presence of display: contents. This is the style against which we have to
260   // do adjustment.
261   scoped_refptr<const ComputedStyle> layout_parent_style_;
262 
263   CSSAnimationUpdate animation_update_;
264   bool is_animation_interpolation_map_ready_ = false;
265   bool has_dir_auto_attribute_ = false;
266   PseudoElementStyleRequest::RequestType pseudo_request_type_;
267 
268   FontBuilder font_builder_;
269 
270   ElementStyleResources element_style_resources_;
271   Element* pseudo_element_;
272   ElementType element_type_;
273 
274   // Properties depended on by the ComputedStyle. This is known after the
275   // cascade is applied.
276   HashSet<CSSPropertyName> dependencies_;
277   // True if there's an entry in 'dependencies_' which does not have the
278   // CSSProperty::kComputedValueComparable flag set.
279   bool has_incomparable_dependency_ = false;
280 
281   // True if the base style can be cached to optimize style recalculations for
282   // animation updates or transition retargeting.
283   bool can_cache_base_style_ = false;
284 };
285 
286 }  // namespace blink
287 
288 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_STYLE_RESOLVER_STATE_H_
289