Chromium Code Reviews| 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 join_name | 15 join_name |
| 16 ) | 16 ) |
| 17 from collections import OrderedDict, defaultdict | 17 from collections import OrderedDict, defaultdict |
| 18 | 18 |
| 19 | 19 |
| 20 # Temporary hard-coded list of fields that are not CSS properties. | 20 # Temporary hard-coded list of extra fields. |
| 21 # TODO(shend): Put this into its own JSON5 file. | 21 # TODO(shend): Put this into its own JSON5 file. |
| 22 NONPROPERTIES = [ | 22 EXTRA_FIELDS = [ |
| 23 {'name': 'IsLink', 'field_template': 'monotonic_flag', | 23 {'name': 'IsLink', 'field_template': 'monotonic_flag', |
| 24 'inherited': False, 'independent': False, 'default_value': False}, | 24 'inherited': False, 'independent': False, 'default_value': False}, |
| 25 {'name': 'OriginalDisplay', 'field_template': 'keyword', 'default_value': 'i nline', | 25 {'name': 'OriginalDisplay', 'field_template': 'keyword', 'default_value': 'i nline', |
| 26 'type_name': 'EDisplay', 'inherited': False, 'independent': False, | 26 'type_name': 'EDisplay', 'inherited': False, 'independent': False, |
| 27 'keywords': [ | 27 'keywords': [ |
| 28 "inline", "block", "list-item", "inline-block", "table", "inline-table" , "table-row-group", "table-header-group", | 28 "inline", "block", "list-item", "inline-block", "table", "inline-table" , "table-row-group", "table-header-group", |
| 29 "table-footer-group", "table-row", "table-column-group", "table-column" , "table-cell", "table-caption", "-webkit-box", | 29 "table-footer-group", "table-row", "table-column-group", "table-column" , "table-cell", "table-caption", "-webkit-box", |
| 30 "-webkit-inline-box", "flex", "inline-flex", "grid", "inline-grid", "co ntents", "flow-root", "none" | 30 "-webkit-inline-box", "flex", "inline-flex", "grid", "inline-grid", "co ntents", "flow-root", "none" |
| 31 ]}, | 31 ]}, |
| 32 {'name': 'InsideLink', 'field_template': 'keyword', 'default_value': 'not-in side-link', | 32 {'name': 'InsideLink', 'field_template': 'keyword', 'default_value': 'not-in side-link', |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 242 type_name='bool', | 242 type_name='bool', |
| 243 field_template='primitive', | 243 field_template='primitive', |
| 244 size=1, | 244 size=1, |
| 245 default_value='true', | 245 default_value='true', |
| 246 getter_method_name=method_name(name_for_methods), | 246 getter_method_name=method_name(name_for_methods), |
| 247 setter_method_name=method_name(join_name('set', name_for_methods)), | 247 setter_method_name=method_name(join_name('set', name_for_methods)), |
| 248 initial_method_name=method_name(join_name('initial', name_for_methods)), | 248 initial_method_name=method_name(join_name('initial', name_for_methods)), |
| 249 ) | 249 ) |
| 250 | 250 |
| 251 | 251 |
| 252 def _create_fields(field_role, properties): | 252 def _create_fields(properties): |
| 253 """ | 253 """ |
| 254 Create ComputedStyle fields from properties or nonproperties and return a li st of Field objects. | 254 Create ComputedStyle fields from properties or nonproperties and return a li st of Field objects. |
| 255 """ | 255 """ |
| 256 fields = [] | 256 fields = [] |
| 257 for property_ in properties: | 257 for property_ in properties: |
| 258 # Only generate properties that have a field template | 258 # Only generate properties that have a field template |
| 259 if property_['field_template'] is not None: | 259 if property_['field_template'] is not None: |
| 260 # If the property is independent, add the single-bit sized isInherit ed flag | 260 # If the property is independent, add the single-bit sized isInherit ed flag |
| 261 # to the list of Fields as well. | 261 # to the list of Fields as well. |
| 262 if property_['independent']: | 262 if property_['independent']: |
| 263 fields.append(_create_inherited_flag_field(property_)) | 263 fields.append(_create_inherited_flag_field(property_)) |
| 264 | 264 |
| 265 # TODO(shend): Get rid of the property/nonproperty field roles. | |
| 266 # If the field has_custom_compare_and_copy, then it does not appear in | |
| 267 # ComputedStyle::operator== and ComputedStyle::CopyNonInheritedFromC ached. | |
| 268 field_role = 'nonproperty' if property_['has_custom_compare_and_copy '] else 'property' | |
| 265 fields.append(_create_field(field_role, property_)) | 269 fields.append(_create_field(field_role, property_)) |
| 266 | 270 |
| 267 return fields | 271 return fields |
| 268 | 272 |
| 269 | 273 |
| 270 def _pack_fields(fields): | 274 def _pack_fields(fields): |
| 271 """ | 275 """ |
| 272 Group a list of fields into buckets to minimise padding. | 276 Group a list of fields into buckets to minimise padding. |
| 273 Returns a list of buckets, where each bucket is a list of Field objects. | 277 Returns a list of buckets, where each bucket is a list of Field objects. |
| 274 """ | 278 """ |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 296 break | 300 break |
| 297 if not added_to_bucket: | 301 if not added_to_bucket: |
| 298 field_buckets.append([field]) | 302 field_buckets.append([field]) |
| 299 | 303 |
| 300 return field_buckets | 304 return field_buckets |
| 301 | 305 |
| 302 | 306 |
| 303 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): | 307 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): |
| 304 def __init__(self, json5_file_path): | 308 def __init__(self, json5_file_path): |
| 305 super(ComputedStyleBaseWriter, self).__init__(json5_file_path) | 309 super(ComputedStyleBaseWriter, self).__init__(json5_file_path) |
| 306 self._outputs = { | |
| 307 'ComputedStyleBase.h': self.generate_base_computed_style_h, | |
| 308 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp, | |
| 309 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co nstants, | |
| 310 } | |
| 311 | |
| 312 # TODO(shend): Remove this once we move NONPROPERTIES to its own JSON fi le, | |
| 313 # since the JSON5 reader will handle missing fields and defaults. | |
| 314 nonproperties = [defaultdict(lambda: None, item) for item in NONPROPERTI ES] | |
| 315 | |
| 316 for property_ in nonproperties: | |
| 317 self._apply_property_naming_defaults(property_) | |
| 318 | 310 |
| 319 # Ignore shorthand properties | 311 # Ignore shorthand properties |
| 320 for property_ in self._properties.values(): | 312 for property_ in self._properties.values(): |
| 321 if property_['field_template'] is not None: | 313 if property_['field_template'] is not None: |
| 322 assert not property_['longhands'], \ | 314 assert not property_['longhands'], \ |
| 323 "Shorthand '{}' cannot have a field_template.".format(proper ty_['name']) | 315 "Shorthand '{}' cannot have a field_template.".format(proper ty_['name']) |
| 324 | 316 |
| 325 property_values = [value for value in self._properties.values() if not v alue['longhands']] | 317 css_properties = [value for value in self._properties.values() if not va lue['longhands']] |
| 326 | 318 |
| 327 for property_ in property_values: | 319 for property_ in css_properties: |
| 328 # Override the type name when field_type_path is specified | 320 # All CSS properties have generated comparison and copy. |
| 329 if property_['field_type_path']: | 321 property_['has_custom_compare_and_copy'] = False |
|
alancutter (OOO until 2018)
2017/04/19 04:40:15
# All CSS properties that are generated do not hav
shend
2017/04/19 07:20:30
Done.
| |
| 330 property_['type_name'] = property_['field_type_path'].split('/') [-1] | |
| 331 # CSS properties are not allowed to explicitly specify their field_s ize. | 322 # CSS properties are not allowed to explicitly specify their field_s ize. |
| 332 property_['field_size'] = None | 323 property_['field_size'] = None |
| 333 | 324 |
| 334 self._generated_enums = _create_enums(property_values + nonproperties) | 325 # TODO(shend): Remove this once we move EXTRA_FIELDS to its own JSON fil e, |
| 326 # since the JSON5 reader will handle missing fields and defaults. | |
| 327 extra_fields = [defaultdict(lambda: None, item) for item in EXTRA_FIELDS ] | |
| 335 | 328 |
| 336 all_fields = (_create_fields('property', property_values) + | 329 for property_ in extra_fields: |
| 337 _create_fields('nonproperty', nonproperties)) | 330 # TODO(shend): Remove the line below once we move EXTRA_FIELDS to it s |
| 331 # own file which would enforce defaults. | |
| 332 property_['has_custom_compare_and_copy'] = True | |
| 333 self._apply_property_naming_defaults(property_) | |
| 334 | |
| 335 all_properties = css_properties + extra_fields | |
| 336 | |
| 337 # Override the type name when field_type_path is specified | |
| 338 for property_ in all_properties: | |
| 339 if property_['field_type_path']: | |
| 340 property_['type_name'] = property_['field_type_path'].split('/') [-1] | |
| 341 | |
| 342 self._generated_enums = _create_enums(all_properties) | |
| 343 | |
| 344 all_fields = _create_fields(all_properties) | |
| 338 | 345 |
| 339 # Separate the normal fields from the bit fields | 346 # Separate the normal fields from the bit fields |
| 340 bit_fields = [field for field in all_fields if field.is_bit_field] | 347 bit_fields = [field for field in all_fields if field.is_bit_field] |
| 341 normal_fields = [field for field in all_fields if not field.is_bit_field ] | 348 normal_fields = [field for field in all_fields if not field.is_bit_field ] |
| 342 | 349 |
| 343 # Pack bit fields into buckets | 350 # Pack bit fields into buckets |
| 344 field_buckets = _pack_fields(bit_fields) | 351 field_buckets = _pack_fields(bit_fields) |
| 345 | 352 |
| 346 # The expected size of ComputedStyleBase is equivalent to as many words | 353 # The expected size of ComputedStyleBase is equivalent to as many words |
| 347 # as the total number of buckets. | 354 # as the total number of buckets. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 364 (self._expected_bit_field_bytes, real_bit_field_bytes)) | 371 (self._expected_bit_field_bytes, real_bit_field_bytes)) |
| 365 | 372 |
| 366 # Normal fields go first, then the bit fields. | 373 # Normal fields go first, then the bit fields. |
| 367 self._fields = list(normal_fields) | 374 self._fields = list(normal_fields) |
| 368 | 375 |
| 369 # Order the fields so fields in each bucket are adjacent. | 376 # Order the fields so fields in each bucket are adjacent. |
| 370 for bucket in field_buckets: | 377 for bucket in field_buckets: |
| 371 for field in bucket: | 378 for field in bucket: |
| 372 self._fields.append(field) | 379 self._fields.append(field) |
| 373 | 380 |
| 374 self._include_paths = _get_include_paths(property_values + nonproperties ) | 381 self._include_paths = _get_include_paths(all_properties) |
| 375 | 382 self._outputs = { |
| 383 'ComputedStyleBase.h': self.generate_base_computed_style_h, | |
| 384 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp, | |
| 385 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co nstants, | |
| 386 } | |
| 376 | 387 |
| 377 @template_expander.use_jinja('ComputedStyleBase.h.tmpl') | 388 @template_expander.use_jinja('ComputedStyleBase.h.tmpl') |
| 378 def generate_base_computed_style_h(self): | 389 def generate_base_computed_style_h(self): |
| 379 return { | 390 return { |
| 380 'properties': self._properties, | 391 'properties': self._properties, |
| 381 'enums': self._generated_enums, | 392 'enums': self._generated_enums, |
| 382 'include_paths': self._include_paths, | 393 'include_paths': self._include_paths, |
| 383 'fields': self._fields, | 394 'fields': self._fields, |
| 384 } | 395 } |
| 385 | 396 |
| 386 @template_expander.use_jinja('ComputedStyleBase.cpp.tmpl') | 397 @template_expander.use_jinja('ComputedStyleBase.cpp.tmpl') |
| 387 def generate_base_computed_style_cpp(self): | 398 def generate_base_computed_style_cpp(self): |
| 388 return { | 399 return { |
| 389 'properties': self._properties, | 400 'properties': self._properties, |
| 390 'enums': self._generated_enums, | 401 'enums': self._generated_enums, |
| 391 'fields': self._fields, | 402 'fields': self._fields, |
| 392 'expected_bit_field_bytes': self._expected_bit_field_bytes, | 403 'expected_bit_field_bytes': self._expected_bit_field_bytes, |
| 393 } | 404 } |
| 394 | 405 |
| 395 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 406 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
| 396 def generate_base_computed_style_constants(self): | 407 def generate_base_computed_style_constants(self): |
| 397 return { | 408 return { |
| 398 'properties': self._properties, | 409 'properties': self._properties, |
| 399 'enums': self._generated_enums, | 410 'enums': self._generated_enums, |
| 400 'fields': self._fields, | 411 'fields': self._fields, |
| 401 } | 412 } |
| 402 | 413 |
| 403 if __name__ == '__main__': | 414 if __name__ == '__main__': |
| 404 json5_generator.Maker(ComputedStyleBaseWriter).main() | 415 json5_generator.Maker(ComputedStyleBaseWriter).main() |
| OLD | NEW |