| 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', 'unsigned', 'int', | 30 'StyleColor', 'Color', '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 pointer_type_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, p
ointer_type_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.pointer_type_name = pointer_type_name |
| 129 self.alignment_type = self.pointer_type_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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 elif property_['field_template'] == 'primitive': | 268 elif property_['field_template'] == 'primitive': |
| 266 type_name = property_['type_name'] | 269 type_name = property_['type_name'] |
| 267 default_value = property_['default_value'] | 270 default_value = property_['default_value'] |
| 268 size = 1 if type_name == 'bool' else None # pack bools with 1 bit. | 271 size = 1 if type_name == 'bool' else None # pack bools with 1 bit. |
| 269 else: | 272 else: |
| 270 assert property_['field_template'] in ('monotonic_flag',) | 273 assert property_['field_template'] in ('monotonic_flag',) |
| 271 type_name = 'bool' | 274 type_name = 'bool' |
| 272 default_value = 'false' | 275 default_value = 'false' |
| 273 size = 1 | 276 size = 1 |
| 274 | 277 |
| 278 if property_['pointer_type_name']: |
| 279 assert property_['field_template'] == 'storage_only' |
| 280 type_name = '{}<{}>'.format(property_['pointer_type_name'], type_name) |
| 281 |
| 275 return Field( | 282 return Field( |
| 276 'property', | 283 'property', |
| 277 name_for_methods, | 284 name_for_methods, |
| 278 property_name=property_['name'], | 285 property_name=property_['name'], |
| 279 inherited=property_['inherited'], | 286 inherited=property_['inherited'], |
| 280 independent=property_['independent'], | 287 independent=property_['independent'], |
| 281 type_name=type_name, | 288 type_name=type_name, |
| 289 pointer_type_name=property_['pointer_type_name'], |
| 282 field_template=property_['field_template'], | 290 field_template=property_['field_template'], |
| 283 field_group=property_['field_group'], | 291 field_group=property_['field_group'], |
| 284 size=size, | 292 size=size, |
| 285 default_value=default_value, | 293 default_value=default_value, |
| 286 has_custom_compare_and_copy=property_['has_custom_compare_and_copy'], | 294 has_custom_compare_and_copy=property_['has_custom_compare_and_copy'], |
| 287 getter_method_name=property_['getter'], | 295 getter_method_name=property_['getter'], |
| 288 setter_method_name=property_['setter'], | 296 setter_method_name=property_['setter'], |
| 289 initial_method_name=property_['initial'], | 297 initial_method_name=property_['initial'], |
| 290 ) | 298 ) |
| 291 | 299 |
| 292 | 300 |
| 293 def _create_inherited_flag_field(property_): | 301 def _create_inherited_flag_field(property_): |
| 294 """ | 302 """ |
| 295 Create the field used for an inheritance fast path from an independent CSS p
roperty, | 303 Create the field used for an inheritance fast path from an independent CSS p
roperty, |
| 296 and return the Field object. | 304 and return the Field object. |
| 297 """ | 305 """ |
| 298 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') | 306 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') |
| 299 return Field( | 307 return Field( |
| 300 'inherited_flag', | 308 'inherited_flag', |
| 301 name_for_methods, | 309 name_for_methods, |
| 302 property_name=property_['name'], | 310 property_name=property_['name'], |
| 303 type_name='bool', | 311 type_name='bool', |
| 312 pointer_type_name=None, |
| 304 field_template='primitive', | 313 field_template='primitive', |
| 305 field_group=property_['field_group'], | 314 field_group=property_['field_group'], |
| 306 size=1, | 315 size=1, |
| 307 default_value='true', | 316 default_value='true', |
| 308 has_custom_compare_and_copy=False, | 317 has_custom_compare_and_copy=False, |
| 309 getter_method_name=method_name(name_for_methods), | 318 getter_method_name=method_name(name_for_methods), |
| 310 setter_method_name=method_name(join_name('set', name_for_methods)), | 319 setter_method_name=method_name(join_name('set', name_for_methods)), |
| 311 initial_method_name=method_name(join_name('initial', name_for_methods)), | 320 initial_method_name=method_name(join_name('initial', name_for_methods)), |
| 312 ) | 321 ) |
| 313 | 322 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 if not added_to_bucket: | 365 if not added_to_bucket: |
| 357 field_buckets.append([field]) | 366 field_buckets.append([field]) |
| 358 | 367 |
| 359 return _flatten_list(field_buckets) | 368 return _flatten_list(field_buckets) |
| 360 | 369 |
| 361 | 370 |
| 362 def _reorder_non_bit_fields(non_bit_fields): | 371 def _reorder_non_bit_fields(non_bit_fields): |
| 363 # A general rule of thumb is to sort members by their alignment requirement | 372 # A general rule of thumb is to sort members by their alignment requirement |
| 364 # (from biggest aligned to smallest). | 373 # (from biggest aligned to smallest). |
| 365 for field in non_bit_fields: | 374 for field in non_bit_fields: |
| 366 assert field.type_name in ALIGNMENT_ORDER, \ | 375 assert field.alignment_type in ALIGNMENT_ORDER, \ |
| 367 "Type {} has unknown alignment. Please update ALIGNMENT_ORDER to inc
lude it.".format(field.type_name) | 376 "Type {} has unknown alignment. Please update ALIGNMENT_ORDER to inc
lude it.".format(field.alignment_type) |
| 368 return list(sorted(non_bit_fields, key=lambda f: ALIGNMENT_ORDER.index(f.typ
e_name))) | 377 return list(sorted(non_bit_fields, key=lambda f: ALIGNMENT_ORDER.index(f.ali
gnment_type))) |
| 369 | 378 |
| 370 | 379 |
| 371 def _reorder_fields(fields): | 380 def _reorder_fields(fields): |
| 372 """ | 381 """ |
| 373 Returns a list of fields ordered to minimise padding. | 382 Returns a list of fields ordered to minimise padding. |
| 374 """ | 383 """ |
| 375 # Separate out bit fields from non bit fields | 384 # Separate out bit fields from non bit fields |
| 376 bit_fields = [field for field in fields if field.is_bit_field] | 385 bit_fields = [field for field in fields if field.is_bit_field] |
| 377 non_bit_fields = [field for field in fields if not field.is_bit_field] | 386 non_bit_fields = [field for field in fields if not field.is_bit_field] |
| 378 | 387 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 | 451 |
| 443 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 452 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
| 444 def generate_base_computed_style_constants(self): | 453 def generate_base_computed_style_constants(self): |
| 445 return { | 454 return { |
| 446 'properties': self._properties, | 455 'properties': self._properties, |
| 447 'enums': self._generated_enums, | 456 'enums': self._generated_enums, |
| 448 } | 457 } |
| 449 | 458 |
| 450 if __name__ == '__main__': | 459 if __name__ == '__main__': |
| 451 json5_generator.Maker(ComputedStyleBaseWriter).main() | 460 json5_generator.Maker(ComputedStyleBaseWriter).main() |
| OLD | NEW |