1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
|
{% from 'templates/macros.tmpl' import print_if %}
{% macro encode(field, value) %}
{% if field.is_bit_field -%}
static_cast<unsigned>({{value}})
{%- else -%}
{{value}}
{%- endif %}
{% endmacro %}
{% macro decode(field, value) %}
{% if field.is_bit_field -%}
static_cast<{{field.type_name}}>({{value}})
{%- else -%}
{{value}}
{%- endif %}
{% endmacro %}
{% macro getter_method_name(field) -%}
{% if 'getter' not in field.computed_style_custom_functions -%}
{{field.getter_method_name}}
{%- else -%}
{{field.internal_getter_method_name}}
{%- endif %}
{%- endmacro %}
{% macro setter_method_name(field) -%}
{% if 'setter' not in field.computed_style_custom_functions -%}
{{field.setter_method_name}}
{%- else -%}
{{field.internal_setter_method_name}}
{%- endif %}
{%- endmacro %}
{% macro resetter_method_name(field) -%}
{% if 'resetter' not in field.computed_style_custom_functions -%}
{{field.resetter_method_name}}
{%- else -%}
{{field.internal_resetter_method_name}}
{%- endif %}
{%- endmacro %}
{% macro mutable_method_name(field) -%}
{{field.internal_mutable_method_name}}
{%- endmacro %}
{% macro bitfield_prefix() -%}
data_.
{%- endmacro %}
{% macro accessor_expression_prefix(field) -%}
{#- Top-level non-tracable fields reside in the `data_` struct. -#}
{#- Derived flags should not be prefixed here, because they must always be read
via a function. -#}
{%- if not field.group.parent and not field.requires_tracing and not field.derived_from -%}
{{bitfield_prefix()}}
{%- endif -%}
{%- endmacro %}
{% macro getter_expression_without_prefix(field) %}
{% for group in field.group.path_without_root() -%}
{{group.member_name}}->
{%- endfor -%}
{# Derived flags compute their value lazily, so we can not access the field directly. #}
{% if field.derived_from -%}
{{getter_method_name(field)}}()
{%- else %}
{{field.name}}
{%- endif %}
{%- endmacro %}
{% macro access_flag(group) -%}
access_.{{group.member_name}}
{%- endmacro %}
{#
Generates nested calls to Access in preparation of modifying a field.
Example: accessing the group of the 'baseline_shift_' field:
Access(Access(svg_data_, access_.svg_data_)->misc_data_, access_.misc_data_)->baseline_shift_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#}
{% macro nested_group_access(group) %}
{% if group.parent.name -%}
Access({{nested_group_access(group.parent)}}->{{group.member_name}}, {{access_flag(group)}})
{%- else -%}
Access({{group.member_name}}, {{access_flag(group)}})
{%- endif -%}
{%- endmacro %}
{% macro setter_expression_without_prefix(field) %}
{% if field.group.name -%}
{{nested_group_access(field.group)}}->
{%- endif -%}
{{field.name}}
{%- endmacro %}
{% macro getter_expression(field) %}
{{accessor_expression_prefix(field)}}{{getter_expression_without_prefix(field)}}
{%- endmacro %}
{% macro setter_expression(field) %}
{{accessor_expression_prefix(field)}}{{setter_expression_without_prefix(field)}}
{%- endmacro %}
{% macro set_if_changed(field, value) %}
{% if field.group.name -%}
if (!({{getter_expression(field)}} == {{value}}))
{{setter_expression(field)}} = {{value}};
{%- else -%}
{{accessor_expression_prefix(field)}}{{field.name}} = {{value}};
{%- endif %}
{% endmacro %}
{% macro move_if_changed(field, value) %}
{% if field.group.name -%}
if (!({{getter_expression(field)}} == {{value}}))
{{setter_expression(field)}} = std::move({{value}});
{%- else -%}
{{accessor_expression_prefix(field)}}{{field.name}} = std::move({{value}});
{%- endif %}
{% endmacro %}
{% macro nonconst_ref(field) %}
{% if field.is_bit_field or field.field_template == 'primitive' -%}
{{field.type_name}}
{%- else -%}
{{field.type_name}}&
{%- endif %}
{% endmacro %}
{% macro const_ref(field) %}
{% if field.is_bit_field or field.field_template == 'primitive' -%}
{{field.type_name}}
{%- else -%}
const {{field.type_name}}&
{%- endif %}
{% endmacro %}
{% macro rvalue_ref(field) -%}
{{field.type_name}}&&
{%- endmacro %}
{% macro group_getter_expression(group) %}
{% for group in group.path_without_root() -%}
{{group.member_name}}{{print_if(not loop.last, "->")}}
{%- endfor -%}
{% endmacro %}
{% macro declare_storage(field) %}
{% if field.is_bit_field %}
{{print_if(field.mutable, "mutable ")}}unsigned {{field.name}} : {{field.size}}; // {{field.type_name}}
{%- elif field.field_template == 'pointer' %}
{{field.wrapper_pointer_name}}<{{field.type_name}}> {{field.name}};
{%- else %}
{{field.type_name}} {{field.name}};
{%- endif %}
{% endmacro %}
{% macro compare(wrapper_pointer_name, expr, other_name) %}
{% if wrapper_pointer_name -%}
base::ValuesEquivalent({{expr}}, {{other_name}}.{{expr}})
{%- else -%}
{{expr}} == {{other_name}}.{{expr}}
{%- endif %}
{% endmacro %}
{% macro compare_expr(wrapper_pointer_name, expr, other_expr) %}
{% if wrapper_pointer_name -%}
base::ValuesEquivalent({{expr}}, {{other_expr}})
{%- else -%}
{{expr}} == {{other_expr}}
{%- endif %}
{% endmacro %}
{# Given a group and a list of fields to compare, this generates a set of
equality comparisons on those fields. The generated comparisons take
advantage of group sharing. #}
{% macro fieldwise_compare(group, fields_to_compare, boolean_and=None) %}
{% set boolean_and = boolean_and or joiner('&& ') %}
{% for subgroup in group.subgroups %}
{# If every field in this subgroup is to be compared, we can compare the
group pointer instead. #}
{% set group_expression = group_getter_expression(subgroup) %}
{% if subgroup.all_fields|rejectattr("custom_compare")|reject("in", fields_to_compare)|list|length == 0 -%}
{{boolean_and()}}base::ValuesEquivalent({{group_expression}}, o.{{group_expression}})
{# Otherwise, we would have to recursively generate comparison operations
on fields in the subgroup. If the objects are the same, we can skip the
per-field comparisons. #}
{% elif subgroup.all_fields|rejectattr("custom_compare")|select("in", fields_to_compare)|list|length > 0 -%}
{{boolean_and()}}({{group_expression}}.Get() == o.{{group_expression}}.Get()
|| ({{fieldwise_compare(subgroup, fields_to_compare)}}))
{% endif %}
{% endfor %}
{% for field in group.fields|rejectattr("custom_compare")|select("in", fields_to_compare) -%}
{{boolean_and()}}{{compare(field.wrapper_pointer_name, getter_expression(field), "o")}}
{% endfor %}
{% endmacro %}
{% macro fieldwise_debug_diff(group, fields_to_compare) %}
{% for subgroup in group.subgroups %}
{{fieldwise_debug_diff(subgroup, fields_to_compare)}}
{% endfor %}
// Group: {{group.name}}
{% for field in group.fields|rejectattr("custom_compare")|select("in", fields_to_compare) -%}
const auto& {{field.name}}_expr = {{getter_expression(field)}};
const auto& o_{{field.name}}_expr = o.{{getter_expression(field)}};
if (!({{compare_expr(field.wrapper_pointer_name, field.name + "_expr", "o_" + field.name + "_expr")}})) {
DebugDiff d;
d.field = DebugField::{{field.name}};
d.actual = DebugStringForField({{field.name}}_expr);
d.correct = DebugStringForField(o_{{field.name}}_expr);
diff.push_back(std::move(d));
}
{% endfor %}
{% endmacro %}
{% macro reset_group_access(group) -%}
{{access_flag(group)}} = false;
{% for subgroup in group.subgroups -%}
{{reset_group_access(subgroup)}}
{%- endfor %}
{%- endmacro %}
{#
The `field_source_expression` and `group_source_expression` are used
for the special two-argument constructor of ComputedStyleBuilderBase,
and provide expressions suited to initialize the given field/group from
one of two sources:
- Non-inherited fields/groups are copied from `non_inherited_source`.
- Inherited fields/groups are copied from `inherited_source`.
- Fields with reset_on_new_style are instead set to their initial values.
Subgroups with a mix of non-inherited and inherited fields are also
initialized in the two-source fashion described above.
#}
{% macro field_source_expression(field, non_inherited_source, inherited_source) -%}
{%- if field.reset_on_new_style -%}
{{encode(field, field.default_value)}} /* {{field.name}}{{print_if(field.mutable, " (mutable)")}} */
{%- elif field.is_inherited -%}
{{inherited_source}}.{{accessor_expression_prefix(field)}}{{field.name}}
{%- else -%}
{{non_inherited_source}}.{{accessor_expression_prefix(field)}}{{field.name}}
{%- endif -%}
{%- endmacro %}
{% macro group_source_expression(group, non_inherited_source, inherited_source) -%}
{% set non_inherited = non_inherited_source + "." + group.member_name %}
{% set inherited = inherited_source + "." + group.member_name %}
{%- if group.all_fields|rejectattr("is_inherited")|list|length == 0 -%}
{{inherited}}
{%- elif group.all_fields|selectattr("is_inherited")|list|length == 0 -%}
{{non_inherited}}
{%- else -%}
{#- Mix of non-inherited and inherited fields. -#}
{{inherited}} == {{non_inherited}}
? {{inherited}}.Get()
: MakeGarbageCollected<{{group.type_name}}>(*{{non_inherited}}, *{{inherited}})
{%- endif -%}
{%- endmacro %}
{% macro fieldwise_pointer_compare_inherited(group, boolean_and=None) %}
{% set boolean_and = boolean_and or joiner('&& ') %}
{% for subgroup in group.subgroups %}
{# If every field in this subgroup is inherited, we directly compare the
group instead, delegating to operator== (with direct pointer comparison
as a fast path). #}
{% set group_expression = group_getter_expression(subgroup) %}
{% if subgroup.all_fields|rejectattr("is_inherited")|list|length == 0 -%}
{{boolean_and()}}base::ValuesEquivalent({{group_expression}}.Get(), o.{{group_expression}}.Get())
{# Otherwise, we would have to recursively generate comparison operations
on fields in the subgroup. #}
{% elif subgroup.all_fields|selectattr("is_inherited")|list|length > 0 -%}
{{boolean_and()}}(base::ValuesEquivalent({{group_expression}}.Get(), o.{{group_expression}}.Get())
|| ({{fieldwise_pointer_compare_inherited(subgroup)}}))
{% endif %}
{% endfor %}
{% for field in group.fields if field.is_inherited -%}
{% if field.wrapper_pointer_name %}
{{boolean_and()}}base::ValuesEquivalent({{getter_expression(field)}}, o.{{getter_expression(field)}})
{% else %}
{{boolean_and()}}{{getter_expression(field)}} == o.{{getter_expression(field)}}
{% endif %}
{% endfor %}
{% endmacro %}
{% macro diff_field(is_pointer_type, expr) %}
{% if is_pointer_type -%}
!base::ValuesEquivalent(a.{{expr}}, b.{{expr}})
{%- else -%}
a.{{expr}} != b.{{expr}}
{%- endif %}
{% endmacro %}
{% macro field_invalidation_diff(group_to_diff) %}
{% for subgroup in group_to_diff.subgroups|selectattr("needs_diff") %}
if (a.{{group_getter_expression(subgroup)}}.Get() != b.{{group_getter_expression(subgroup)}}.Get()) {
{{field_invalidation_diff(subgroup)|indent(2, true)}}
}
{% endfor %}
{% for field in group_to_diff.fields|selectattr("needs_diff") %}
if ({{diff_field(field.wrapper_pointer_name, getter_expression(field))}}) {
{% for invalidate in field.invalidate %}
diff |= {{invalidate}};
{% endfor %}
}
{% endfor %}
{% endmacro %}
|