| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2016 The Chromium Authors. All rights reserved. | 2 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 import math | 6 import math |
| 7 import sys | 7 import sys |
| 8 | 8 |
| 9 import json5_generator | 9 import json5_generator |
| 10 import template_expander | 10 import template_expander |
| 11 import make_style_builder | 11 import make_style_builder |
| 12 | 12 |
| 13 from name_utilities import ( | 13 from name_utilities import ( |
| 14 enum_for_css_keyword, enum_type_name, enum_value_name, class_member_name, me
thod_name, | 14 enum_for_css_keyword, enum_type_name, enum_value_name, class_member_name, me
thod_name, |
| 15 class_name, join_name | 15 class_name, join_name |
| 16 ) | 16 ) |
| 17 from collections import defaultdict, OrderedDict | 17 from collections import defaultdict, OrderedDict |
| 18 from itertools import chain | 18 from itertools import chain |
| 19 | 19 |
| 20 # Heuristic ordering of types from largest to smallest, used to sort fields by t
heir alignment sizes. | 20 # Heuristic ordering of types from largest to smallest, used to sort fields by t
heir alignment sizes. |
| 21 # Specifying the exact alignment sizes for each type is impossible because it's
platform specific, | 21 # Specifying the exact alignment sizes for each type is impossible because it's
platform specific, |
| 22 # so we define an ordering instead. | 22 # so we define an ordering instead. |
| 23 # The ordering comes from the data obtained in: | 23 # The ordering comes from the data obtained in: |
| 24 # https://codereview.chromium.org/2841413002 | 24 # https://codereview.chromium.org/2841413002 |
| 25 # TODO(shend): Put alignment sizes into code form, rather than linking to a CL w
hich may disappear. | 25 # TODO(shend): Put alignment sizes into code form, rather than linking to a CL w
hich may disappear. |
| 26 ALIGNMENT_ORDER = [ | 26 ALIGNMENT_ORDER = [ |
| 27 'double', | 27 'double', |
| 28 'Font', 'FillLayer', 'NinePieceImage', # Aligns like a void * (can be 32 or
64 bits) | 28 'AtomicString', 'RefPtr', 'Persistent', 'Font', 'FillLayer', 'NinePieceImage
', # Aligns like a pointer (can be 32 or 64 bits) |
| 29 'LengthBox', 'LengthSize', 'Length', 'float', | 29 'LengthBox', 'LengthSize', 'Length', 'TextSizeAdjust', 'TabSize', 'float', |
| 30 'StyleColor', 'Color', 'LayoutUnit', 'unsigned', 'int', | 30 'StyleColor', 'Color', 'LayoutUnit', 'unsigned', 'int', |
| 31 'short', | 31 'short', |
| 32 'char', | 32 'uint8_t', 'char', |
| 33 'bool' | 33 'bool' |
| 34 ] | 34 ] |
| 35 | 35 |
| 36 # TODO(shend): Improve documentation and add docstrings. | 36 # TODO(shend): Improve documentation and add docstrings. |
| 37 | 37 |
| 38 | 38 |
| 39 def _flatten_list(x): | 39 def _flatten_list(x): |
| 40 """Flattens a list of lists into a single list.""" | 40 """Flattens a list of lists into a single list.""" |
| 41 return list(chain.from_iterable(x)) | 41 return list(chain.from_iterable(x)) |
| 42 | 42 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 | 103 |
| 104 Attributes: | 104 Attributes: |
| 105 field_role: The semantic role of the field. Can be: | 105 field_role: The semantic role of the field. Can be: |
| 106 - 'property': for fields that store CSS properties | 106 - 'property': for fields that store CSS properties |
| 107 - 'inherited_flag': for single-bit flags that store whether a proper
ty is | 107 - 'inherited_flag': for single-bit flags that store whether a proper
ty is |
| 108 inherited by this style or set explicitly | 108 inherited by this style or set explicitly |
| 109 name_for_methods: String used to form the names of getters and setters. | 109 name_for_methods: String used to form the names of getters and setters. |
| 110 Should be in upper camel case. | 110 Should be in upper camel case. |
| 111 property_name: Name of the property that the field is part of. | 111 property_name: Name of the property that the field is part of. |
| 112 type_name: Name of the C++ type exposed by the generated interface (e.g.
EClear, int). | 112 type_name: Name of the C++ type exposed by the generated interface (e.g.
EClear, int). |
| 113 wrapper_pointer_name: Name of the pointer type that wraps this field (e.
g. RefPtr). |
| 113 field_template: Determines the interface generated for the field. Can be
one of: | 114 field_template: Determines the interface generated for the field. Can be
one of: |
| 114 keyword, flag, or monotonic_flag. | 115 keyword, flag, or monotonic_flag. |
| 115 field_group: The name of the group that this field is inside. | 116 field_group: The name of the group that this field is inside. |
| 116 size: Number of bits needed for storage. | 117 size: Number of bits needed for storage. |
| 117 default_value: Default value for this field when it is first initialized
. | 118 default_value: Default value for this field when it is first initialized
. |
| 118 """ | 119 """ |
| 119 | 120 |
| 120 def __init__(self, field_role, name_for_methods, property_name, type_name, | 121 def __init__(self, field_role, name_for_methods, property_name, type_name, w
rapper_pointer_name, |
| 121 field_template, field_group, size, default_value, has_custom_co
mpare_and_copy, | 122 field_template, field_group, size, default_value, has_custom_co
mpare_and_copy, |
| 122 getter_method_name, setter_method_name, initial_method_name, **
kwargs): | 123 getter_method_name, setter_method_name, initial_method_name, **
kwargs): |
| 123 """Creates a new field.""" | 124 """Creates a new field.""" |
| 124 self.name = class_member_name(name_for_methods) | 125 self.name = class_member_name(name_for_methods) |
| 125 self.property_name = property_name | 126 self.property_name = property_name |
| 126 self.type_name = type_name | 127 self.type_name = type_name |
| 128 self.wrapper_pointer_name = wrapper_pointer_name |
| 129 self.alignment_type = self.wrapper_pointer_name or self.type_name |
| 127 self.field_template = field_template | 130 self.field_template = field_template |
| 128 self.group_name = field_group | 131 self.group_name = field_group |
| 129 self.group_member_name = class_member_name(join_name(field_group, 'data'
)) if field_group else None | 132 self.group_member_name = class_member_name(join_name(field_group, 'data'
)) if field_group else None |
| 130 self.size = size | 133 self.size = size |
| 131 self.default_value = default_value | 134 self.default_value = default_value |
| 132 self.has_custom_compare_and_copy = has_custom_compare_and_copy | 135 self.has_custom_compare_and_copy = has_custom_compare_and_copy |
| 133 | 136 |
| 134 # Field role: one of these must be true | 137 # Field role: one of these must be true |
| 135 self.is_property = field_role == 'property' | 138 self.is_property = field_role == 'property' |
| 136 self.is_inherited_flag = field_role == 'inherited_flag' | 139 self.is_inherited_flag = field_role == 'inherited_flag' |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 elif property_['field_template'] == 'primitive': | 269 elif property_['field_template'] == 'primitive': |
| 267 type_name = property_['type_name'] | 270 type_name = property_['type_name'] |
| 268 default_value = property_['default_value'] | 271 default_value = property_['default_value'] |
| 269 size = 1 if type_name == 'bool' else None # pack bools with 1 bit. | 272 size = 1 if type_name == 'bool' else None # pack bools with 1 bit. |
| 270 else: | 273 else: |
| 271 assert property_['field_template'] in ('monotonic_flag',) | 274 assert property_['field_template'] in ('monotonic_flag',) |
| 272 type_name = 'bool' | 275 type_name = 'bool' |
| 273 default_value = 'false' | 276 default_value = 'false' |
| 274 size = 1 | 277 size = 1 |
| 275 | 278 |
| 279 if property_['wrapper_pointer_name']: |
| 280 assert property_['field_template'] == 'storage_only' |
| 281 type_name = '{}<{}>'.format(property_['wrapper_pointer_name'], type_name
) |
| 282 |
| 276 return Field( | 283 return Field( |
| 277 'property', | 284 'property', |
| 278 name_for_methods, | 285 name_for_methods, |
| 279 property_name=property_['name'], | 286 property_name=property_['name'], |
| 280 inherited=property_['inherited'], | 287 inherited=property_['inherited'], |
| 281 independent=property_['independent'], | 288 independent=property_['independent'], |
| 282 type_name=type_name, | 289 type_name=type_name, |
| 290 wrapper_pointer_name=property_['wrapper_pointer_name'], |
| 283 field_template=property_['field_template'], | 291 field_template=property_['field_template'], |
| 284 field_group=property_['field_group'], | 292 field_group=property_['field_group'], |
| 285 size=size, | 293 size=size, |
| 286 default_value=default_value, | 294 default_value=default_value, |
| 287 has_custom_compare_and_copy=property_['has_custom_compare_and_copy'], | 295 has_custom_compare_and_copy=property_['has_custom_compare_and_copy'], |
| 288 getter_method_name=property_['getter'], | 296 getter_method_name=property_['getter'], |
| 289 setter_method_name=property_['setter'], | 297 setter_method_name=property_['setter'], |
| 290 initial_method_name=property_['initial'], | 298 initial_method_name=property_['initial'], |
| 291 ) | 299 ) |
| 292 | 300 |
| 293 | 301 |
| 294 def _create_inherited_flag_field(property_): | 302 def _create_inherited_flag_field(property_): |
| 295 """ | 303 """ |
| 296 Create the field used for an inheritance fast path from an independent CSS p
roperty, | 304 Create the field used for an inheritance fast path from an independent CSS p
roperty, |
| 297 and return the Field object. | 305 and return the Field object. |
| 298 """ | 306 """ |
| 299 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') | 307 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') |
| 300 return Field( | 308 return Field( |
| 301 'inherited_flag', | 309 'inherited_flag', |
| 302 name_for_methods, | 310 name_for_methods, |
| 303 property_name=property_['name'], | 311 property_name=property_['name'], |
| 304 type_name='bool', | 312 type_name='bool', |
| 313 wrapper_pointer_name=None, |
| 305 field_template='primitive', | 314 field_template='primitive', |
| 306 field_group=property_['field_group'], | 315 field_group=property_['field_group'], |
| 307 size=1, | 316 size=1, |
| 308 default_value='true', | 317 default_value='true', |
| 309 has_custom_compare_and_copy=False, | 318 has_custom_compare_and_copy=False, |
| 310 getter_method_name=method_name(name_for_methods), | 319 getter_method_name=method_name(name_for_methods), |
| 311 setter_method_name=method_name(join_name('set', name_for_methods)), | 320 setter_method_name=method_name(join_name('set', name_for_methods)), |
| 312 initial_method_name=method_name(join_name('initial', name_for_methods)), | 321 initial_method_name=method_name(join_name('initial', name_for_methods)), |
| 313 ) | 322 ) |
| 314 | 323 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 if not added_to_bucket: | 366 if not added_to_bucket: |
| 358 field_buckets.append([field]) | 367 field_buckets.append([field]) |
| 359 | 368 |
| 360 return _flatten_list(field_buckets) | 369 return _flatten_list(field_buckets) |
| 361 | 370 |
| 362 | 371 |
| 363 def _reorder_non_bit_fields(non_bit_fields): | 372 def _reorder_non_bit_fields(non_bit_fields): |
| 364 # A general rule of thumb is to sort members by their alignment requirement | 373 # A general rule of thumb is to sort members by their alignment requirement |
| 365 # (from biggest aligned to smallest). | 374 # (from biggest aligned to smallest). |
| 366 for field in non_bit_fields: | 375 for field in non_bit_fields: |
| 367 assert field.type_name in ALIGNMENT_ORDER, \ | 376 assert field.alignment_type in ALIGNMENT_ORDER, \ |
| 368 "Type {} has unknown alignment. Please update ALIGNMENT_ORDER to inc
lude it.".format(field.type_name) | 377 "Type {} has unknown alignment. Please update ALIGNMENT_ORDER to inc
lude it.".format(field.alignment_type) |
| 369 return list(sorted(non_bit_fields, key=lambda f: ALIGNMENT_ORDER.index(f.typ
e_name))) | 378 return list(sorted(non_bit_fields, key=lambda f: ALIGNMENT_ORDER.index(f.ali
gnment_type))) |
| 370 | 379 |
| 371 | 380 |
| 372 def _reorder_fields(fields): | 381 def _reorder_fields(fields): |
| 373 """ | 382 """ |
| 374 Returns a list of fields ordered to minimise padding. | 383 Returns a list of fields ordered to minimise padding. |
| 375 """ | 384 """ |
| 376 # Separate out bit fields from non bit fields | 385 # Separate out bit fields from non bit fields |
| 377 bit_fields = [field for field in fields if field.is_bit_field] | 386 bit_fields = [field for field in fields if field.is_bit_field] |
| 378 non_bit_fields = [field for field in fields if not field.is_bit_field] | 387 non_bit_fields = [field for field in fields if not field.is_bit_field] |
| 379 | 388 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 | 452 |
| 444 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 453 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
| 445 def generate_base_computed_style_constants(self): | 454 def generate_base_computed_style_constants(self): |
| 446 return { | 455 return { |
| 447 'properties': self._properties, | 456 'properties': self._properties, |
| 448 'enums': self._generated_enums, | 457 'enums': self._generated_enums, |
| 449 } | 458 } |
| 450 | 459 |
| 451 if __name__ == '__main__': | 460 if __name__ == '__main__': |
| 452 json5_generator.Maker(ComputedStyleBaseWriter).main() | 461 json5_generator.Maker(ComputedStyleBaseWriter).main() |
| OLD | NEW |