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 |