| 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 | 17 from collections import OrderedDict |
| 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 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 type_name='bool', | 246 type_name='bool', |
| 247 field_template='primitive', | 247 field_template='primitive', |
| 248 size=1, | 248 size=1, |
| 249 default_value='true', | 249 default_value='true', |
| 250 getter_method_name=method_name(name_for_methods), | 250 getter_method_name=method_name(name_for_methods), |
| 251 setter_method_name=method_name(join_name('set', name_for_methods)), | 251 setter_method_name=method_name(join_name('set', name_for_methods)), |
| 252 initial_method_name=method_name(join_name('initial', name_for_methods)), | 252 initial_method_name=method_name(join_name('initial', name_for_methods)), |
| 253 ) | 253 ) |
| 254 | 254 |
| 255 | 255 |
| 256 def _create_fields(field_role, properties): | 256 def _create_fields(properties): |
| 257 """ | 257 """ |
| 258 Create ComputedStyle fields from properties or nonproperties and return a li
st of Field objects. | 258 Create ComputedStyle fields from properties or nonproperties and return a li
st of Field objects. |
| 259 """ | 259 """ |
| 260 fields = [] | 260 fields = [] |
| 261 for property_ in properties: | 261 for property_ in properties: |
| 262 # Only generate properties that have a field template | 262 # Only generate properties that have a field template |
| 263 if property_['field_template'] is not None: | 263 if property_['field_template'] is not None: |
| 264 # If the property is independent, add the single-bit sized isInherit
ed flag | 264 # If the property is independent, add the single-bit sized isInherit
ed flag |
| 265 # to the list of Fields as well. | 265 # to the list of Fields as well. |
| 266 if property_['independent']: | 266 if property_['independent']: |
| 267 fields.append(_create_inherited_flag_field(property_)) | 267 fields.append(_create_inherited_flag_field(property_)) |
| 268 | 268 |
| 269 # TODO(shend): Get rid of the property/nonproperty field roles. |
| 270 # If the field has_custom_compare_and_copy, then it does not appear
in |
| 271 # ComputedStyle::operator== and ComputedStyle::CopyNonInheritedFromC
ached. |
| 272 field_role = 'nonproperty' if property_['has_custom_compare_and_copy
'] else 'property' |
| 269 fields.append(_create_field(field_role, property_)) | 273 fields.append(_create_field(field_role, property_)) |
| 270 | 274 |
| 271 return fields | 275 return fields |
| 272 | 276 |
| 273 | 277 |
| 274 def _pack_fields(fields): | 278 def _pack_fields(fields): |
| 275 """ | 279 """ |
| 276 Group a list of fields into buckets to minimise padding. | 280 Group a list of fields into buckets to minimise padding. |
| 277 Returns a list of buckets, where each bucket is a list of Field objects. | 281 Returns a list of buckets, where each bucket is a list of Field objects. |
| 278 """ | 282 """ |
| (...skipping 21 matching lines...) Expand all Loading... |
| 300 break | 304 break |
| 301 if not added_to_bucket: | 305 if not added_to_bucket: |
| 302 field_buckets.append([field]) | 306 field_buckets.append([field]) |
| 303 | 307 |
| 304 return field_buckets | 308 return field_buckets |
| 305 | 309 |
| 306 | 310 |
| 307 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): | 311 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): |
| 308 def __init__(self, json5_file_path): | 312 def __init__(self, json5_file_path): |
| 309 super(ComputedStyleBaseWriter, self).__init__(json5_file_path) | 313 super(ComputedStyleBaseWriter, self).__init__(json5_file_path) |
| 310 self._outputs = { | |
| 311 'ComputedStyleBase.h': self.generate_base_computed_style_h, | |
| 312 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp, | |
| 313 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co
nstants, | |
| 314 } | |
| 315 | |
| 316 # TODO(shend): Remove this once we move NONPROPERTIES to its own JSON fi
le, | |
| 317 # since the JSON5 reader will handle missing fields and defaults. | |
| 318 for property_ in NONPROPERTIES: | |
| 319 for parameter in self.json5_file.parameters: | |
| 320 if parameter not in property_: | |
| 321 property_[parameter] = None | |
| 322 | |
| 323 for property_ in NONPROPERTIES: | |
| 324 make_style_builder.apply_property_naming_defaults(property_) | |
| 325 | 314 |
| 326 # Ignore shorthand properties | 315 # Ignore shorthand properties |
| 327 for property_ in self._properties.values(): | 316 for property_ in self._properties.values(): |
| 328 if property_['field_template'] is not None: | 317 if property_['field_template'] is not None: |
| 329 assert not property_['longhands'], \ | 318 assert not property_['longhands'], \ |
| 330 "Shorthand '{}' cannot have a field_template.".format(proper
ty_['name']) | 319 "Shorthand '{}' cannot have a field_template.".format(proper
ty_['name']) |
| 331 | 320 |
| 332 property_values = [value for value in self._properties.values() if not v
alue['longhands']] | 321 css_properties = [value for value in self._properties.values() if not va
lue['longhands']] |
| 333 | 322 |
| 334 for property_ in property_values: | 323 for property_ in css_properties: |
| 335 # Override the type name when field_type_path is specified | 324 # All CSS properties that are generated do not have custom compariso
n and copy logic. |
| 336 if property_['field_type_path']: | 325 property_['has_custom_compare_and_copy'] = False |
| 337 property_['type_name'] = property_['field_type_path'].split('/')
[-1] | |
| 338 # CSS properties are not allowed to explicitly specify their field_s
ize. | 326 # CSS properties are not allowed to explicitly specify their field_s
ize. |
| 339 property_['field_size'] = None | 327 property_['field_size'] = None |
| 340 | 328 |
| 341 self._generated_enums = _create_enums(property_values + NONPROPERTIES) | 329 # TODO(shend): Remove this once we move EXTRA_FIELDS to its own JSON fil
e, |
| 330 # since the JSON5 reader will handle missing fields and defaults. |
| 331 for property_ in EXTRA_FIELDS: |
| 332 for parameter in self.json5_file.parameters: |
| 333 if parameter not in property_: |
| 334 property_[parameter] = None |
| 342 | 335 |
| 343 all_fields = (_create_fields('property', property_values) + | 336 for property_ in EXTRA_FIELDS: |
| 344 _create_fields('nonproperty', NONPROPERTIES)) | 337 # TODO(shend): Remove the line below once we move EXTRA_FIELDS to it
s |
| 338 # own file which would enforce defaults. |
| 339 property_['has_custom_compare_and_copy'] = True |
| 340 make_style_builder.apply_property_naming_defaults(property_) |
| 341 |
| 342 all_properties = css_properties + EXTRA_FIELDS |
| 343 |
| 344 # Override the type name when field_type_path is specified |
| 345 for property_ in all_properties: |
| 346 if property_['field_type_path']: |
| 347 property_['type_name'] = property_['field_type_path'].split('/')
[-1] |
| 348 |
| 349 self._generated_enums = _create_enums(all_properties) |
| 350 |
| 351 all_fields = _create_fields(all_properties) |
| 345 | 352 |
| 346 # Separate the normal fields from the bit fields | 353 # Separate the normal fields from the bit fields |
| 347 bit_fields = [field for field in all_fields if field.is_bit_field] | 354 bit_fields = [field for field in all_fields if field.is_bit_field] |
| 348 normal_fields = [field for field in all_fields if not field.is_bit_field
] | 355 normal_fields = [field for field in all_fields if not field.is_bit_field
] |
| 349 | 356 |
| 350 # Pack bit fields into buckets | 357 # Pack bit fields into buckets |
| 351 field_buckets = _pack_fields(bit_fields) | 358 field_buckets = _pack_fields(bit_fields) |
| 352 | 359 |
| 353 # The expected size of ComputedStyleBase is equivalent to as many words | 360 # The expected size of ComputedStyleBase is equivalent to as many words |
| 354 # as the total number of buckets. | 361 # as the total number of buckets. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 371 (self._expected_bit_field_bytes, real_bit_field_bytes)) | 378 (self._expected_bit_field_bytes, real_bit_field_bytes)) |
| 372 | 379 |
| 373 # Normal fields go first, then the bit fields. | 380 # Normal fields go first, then the bit fields. |
| 374 self._fields = list(normal_fields) | 381 self._fields = list(normal_fields) |
| 375 | 382 |
| 376 # Order the fields so fields in each bucket are adjacent. | 383 # Order the fields so fields in each bucket are adjacent. |
| 377 for bucket in field_buckets: | 384 for bucket in field_buckets: |
| 378 for field in bucket: | 385 for field in bucket: |
| 379 self._fields.append(field) | 386 self._fields.append(field) |
| 380 | 387 |
| 381 self._include_paths = _get_include_paths(property_values + NONPROPERTIES
) | 388 self._include_paths = _get_include_paths(all_properties) |
| 382 | 389 self._outputs = { |
| 390 'ComputedStyleBase.h': self.generate_base_computed_style_h, |
| 391 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp, |
| 392 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co
nstants, |
| 393 } |
| 383 | 394 |
| 384 @template_expander.use_jinja('ComputedStyleBase.h.tmpl') | 395 @template_expander.use_jinja('ComputedStyleBase.h.tmpl') |
| 385 def generate_base_computed_style_h(self): | 396 def generate_base_computed_style_h(self): |
| 386 return { | 397 return { |
| 387 'properties': self._properties, | 398 'properties': self._properties, |
| 388 'enums': self._generated_enums, | 399 'enums': self._generated_enums, |
| 389 'include_paths': self._include_paths, | 400 'include_paths': self._include_paths, |
| 390 'fields': self._fields, | 401 'fields': self._fields, |
| 391 } | 402 } |
| 392 | 403 |
| 393 @template_expander.use_jinja('ComputedStyleBase.cpp.tmpl') | 404 @template_expander.use_jinja('ComputedStyleBase.cpp.tmpl') |
| 394 def generate_base_computed_style_cpp(self): | 405 def generate_base_computed_style_cpp(self): |
| 395 return { | 406 return { |
| 396 'properties': self._properties, | 407 'properties': self._properties, |
| 397 'enums': self._generated_enums, | 408 'enums': self._generated_enums, |
| 398 'fields': self._fields, | 409 'fields': self._fields, |
| 399 'expected_bit_field_bytes': self._expected_bit_field_bytes, | 410 'expected_bit_field_bytes': self._expected_bit_field_bytes, |
| 400 } | 411 } |
| 401 | 412 |
| 402 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 413 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
| 403 def generate_base_computed_style_constants(self): | 414 def generate_base_computed_style_constants(self): |
| 404 return { | 415 return { |
| 405 'properties': self._properties, | 416 'properties': self._properties, |
| 406 'enums': self._generated_enums, | 417 'enums': self._generated_enums, |
| 407 'fields': self._fields, | 418 'fields': self._fields, |
| 408 } | 419 } |
| 409 | 420 |
| 410 if __name__ == '__main__': | 421 if __name__ == '__main__': |
| 411 json5_generator.Maker(ComputedStyleBaseWriter).main() | 422 json5_generator.Maker(ComputedStyleBaseWriter).main() |
| OLD | NEW |