1{% from 'templates/macros.tmpl' import license, print_if, source_files_for_generated_file %}
2{% from 'templates/fields/field.tmpl' import encode, getter_expression, setter_expression, declare_storage, fieldwise_compare, fieldwise_copy, fieldwise_diff, fieldwise_pointer_compare_inherited %}
3{% from 'templates/fields/group.tmpl' import declare_field_group_class %}
4{{license()}}
5
6{{source_files_for_generated_file(template_file, input_files)}}
7
8#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_COMPUTED_STYLE_BASE_H_
9#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_COMPUTED_STYLE_BASE_H_
10
11#include "third_party/blink/renderer/core/core_export.h"
12#include "third_party/blink/renderer/core/layout/layout_theme.h"
13#include "third_party/blink/renderer/core/style/computed_style_constants.h"
14#include "third_party/blink/renderer/core/style/data_ref.h"
15#include "third_party/blink/renderer/core/style/member_copy.h"
16#include "third_party/blink/renderer/core/style/computed_style_initial_values.h"
17{% for path in include_paths %}
18#include "{{path}}"
19{% endfor %}
20
21{# Each field template has macros that we can call to generate specific
22   aspects of the field (e.g. getters, setters).
23#}
24{% import 'templates/fields/keyword.tmpl' as keyword %}
25{% import 'templates/fields/multi_keyword.tmpl' as multi_keyword %}
26{% import 'templates/fields/primitive.tmpl' as primitive %}
27{% import 'templates/fields/monotonic_flag.tmpl' as monotonic_flag %}
28{% import 'templates/fields/external.tmpl' as external %}
29{% import 'templates/fields/pointer.tmpl' as pointer %}
30{% from 'templates/fields/field.tmpl' import encode %}
31{% set field_templates = {
32     'keyword': keyword,
33     'multi_keyword': multi_keyword,
34     'primitive': primitive,
35     'monotonic_flag': monotonic_flag,
36     'external': external,
37     'pointer': pointer
38   } %}
39
40namespace blink {
41
42// Forward declaration for diff functions.
43class ComputedStyle;
44
45// The generated portion of ComputedStyle. For more info, see the header comment
46// in ComputedStyle.h.
47//
48// ComputedStyleBase is a generated class that stores data members or 'fields'
49// used in ComputedStyle. These fields can represent CSS properties or internal
50// style information.
51//
52// STORAGE:
53//
54// Fields are organised in a tree structure, where a node (called a 'group')
55// stores a set of fields and a set of pointers to child nodes (called
56// 'subgroups'). We can visualise the tree structure with ComputedStyleBase as
57// the root node:
58//
59// ComputedStyleBase (fields: display, vertical-align, ...)
60//  |- StyleSurroundData (fields: padding, border, ...)
61//  |- StyleBoxData (fields: width, height, ...)
62//  |- ...
63//  |- StyleRareNonInheritedData (fields: box-shadow, text-overflow, ...)
64//      |- StyleFlexibleBoxData (fields: flex-direction, flex-wrap, ...)
65//      |- ...
66//
67// This design saves memory by allowing multiple ComputedStyleBases to share the
68// same instance of a subgroup. For example, if a page never uses flex box
69// properties, then every ComputedStyleBase can share the same instance of
70// StyleFlexibleBoxData. Without this sharing, we would need to allocate a copy
71// of all the flex box fields for every ComputedStyleBase. Similarly, when an
72// element inherits from its parent, its ComputedStyleBase can simply share all
73// of its subgroups with the parent's.
74//
75// INTERFACE:
76//
77// The functions generated for a field is determined by its 'template'. For
78// example, a field with the 'keyword' template has only one setter, whereas an
79// 'external' field has an extra setter that takes an rvalue reference. A list
80// of the available templates can be found in css_properties.json5.
81class ComputedStyleBase {
82 public:
83  inline bool IndependentInheritedEqual(const ComputedStyleBase& o) const {
84    return (
85        {{fieldwise_compare(computed_style, computed_style.all_fields
86            |selectattr("is_property")
87            |selectattr("is_inherited")
88            |selectattr("is_independent")
89            |list
90          )|indent(8)}}
91    );
92  }
93
94  inline bool NonIndependentInheritedEqual(const ComputedStyleBase& o) const {
95    return (
96        {{fieldwise_compare(computed_style, computed_style.all_fields
97            |selectattr("is_property")
98            |selectattr("is_inherited")
99            |rejectattr("is_independent")
100            |list
101          )|indent(8)}}
102    );
103  }
104
105  inline bool InheritedEqual(const ComputedStyleBase& o) const {
106    return IndependentInheritedEqual(o) && NonIndependentInheritedEqual(o);
107  }
108
109  inline bool NonInheritedEqual(const ComputedStyleBase& o) const {
110    return (
111        {{fieldwise_compare(computed_style, computed_style.all_fields
112            |selectattr("is_property")
113            |rejectattr("is_inherited")
114            |list
115          )|indent(8)}}
116    );
117  }
118
119  inline bool InheritedDataShared(const ComputedStyleBase& o) const {
120    return (
121        {{fieldwise_pointer_compare_inherited(computed_style)|indent(8)}}
122    );
123  }
124
125  enum IsAtShadowBoundary {
126    kAtShadowBoundary,
127    kNotAtShadowBoundary,
128  };
129
130  void InheritFrom(const ComputedStyleBase& other,
131                                      IsAtShadowBoundary isAtShadowBoundary);
132
133  void CopyNonInheritedFromCached(
134      const ComputedStyleBase& other);
135
136  // Copies the values of any independent inherited properties from the parent
137  // style that are marked as inherited by this style.
138  void PropagateIndependentInheritedProperties(
139      const ComputedStyleBase& parentStyle);
140
141  {% for name, groups_to_diff in diff_functions_map.items() %}
142  static bool {{name}}(const ComputedStyle& a, const ComputedStyle& b);
143  {% endfor %}
144
145  // Fields.
146  // TODO(sashab): Remove initialFoo() static methods and update callers to
147  // use resetFoo(), which can be more efficient.
148
149  {% for field in computed_style.all_fields|sort(attribute='name') %}
150  // {{field.property_name}}
151  {{field_templates[field.field_template].decl_public_methods(field)|indent(2)}}
152
153  {% endfor %}
154 private:
155  {% for subgroup in computed_style.subgroups %}
156  {{declare_field_group_class(subgroup)|indent(2)}}
157
158  {% endfor %}
159
160 protected:
161  // Constructor and destructor are protected so that only the parent class ComputedStyle
162  // can instantiate this class.
163  ComputedStyleBase();
164
165  {% for field in computed_style.all_fields|sort(attribute='name') %}
166  {% if field.field_template not in ('pointer',) %}
167  // {{field.property_name}}
168  {{field_templates[field.field_template].decl_protected_methods(field)|indent(2)}}
169
170  {% endif %}
171  {% endfor %}
172
173  ~ComputedStyleBase() = default;
174
175 private:
176  // Storage.
177  {% for subgroup in computed_style.subgroups %}
178  DataRef<{{subgroup.type_name}}> {{subgroup.member_name}};
179  {% endfor %}
180
181  {% for field in computed_style.fields %}
182  {{declare_storage(field)}}
183  {% endfor %}
184};
185
186}  // namespace blink
187
188#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_COMPUTED_STYLE_BASE_H_
189