| 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 extra fields. | |
| 21 # TODO(shend): Put this into its own JSON5 file. | |
| 22 EXTRA_FIELDS = [ | |
| 23 {'name': 'IsLink', 'field_template': 'monotonic_flag', | |
| 24 'inherited': False, 'independent': False, 'default_value': False}, | |
| 25 {'name': 'OriginalDisplay', 'field_template': 'keyword', 'default_value': 'i
nline', | |
| 26 'type_name': 'EDisplay', 'inherited': False, 'independent': False, | |
| 27 'keywords': [ | |
| 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", | |
| 30 "-webkit-inline-box", "flex", "inline-flex", "grid", "inline-grid", "co
ntents", "flow-root", "none" | |
| 31 ]}, | |
| 32 {'name': 'InsideLink', 'field_template': 'keyword', 'default_value': 'not-in
side-link', | |
| 33 'keywords': ['not-inside-link', 'inside-unvisited-link', 'inside-visited-li
nk'], | |
| 34 'inherited': True, 'independent': False}, | |
| 35 # Style can not be shared. | |
| 36 {'name': 'Unique', 'field_template': 'monotonic_flag', | |
| 37 'inherited': False, 'independent': False, 'default_value': False}, | |
| 38 # Whether this style is affected by these pseudo-classes. | |
| 39 {'name': 'AffectedByFocus', 'field_template': 'monotonic_flag', | |
| 40 'inherited': False, 'independent': False, 'default_value': False}, | |
| 41 {'name': 'AffectedByFocusWithin', 'field_template': 'monotonic_flag', | |
| 42 'inherited': False, 'independent': False, 'default_value': False}, | |
| 43 {'name': 'AffectedByHover', 'field_template': 'monotonic_flag', | |
| 44 'inherited': False, 'independent': False, 'default_value': False}, | |
| 45 {'name': 'AffectedByActive', 'field_template': 'monotonic_flag', | |
| 46 'inherited': False, 'independent': False, 'default_value': False}, | |
| 47 {'name': 'AffectedByDrag', 'field_template': 'monotonic_flag', | |
| 48 'inherited': False, 'independent': False, 'default_value': False}, | |
| 49 # A non-inherited property references a variable or @apply is used | |
| 50 {'name': 'HasVariableReferenceFromNonInheritedProperty', 'field_template': '
monotonic_flag', | |
| 51 'inherited': False, 'independent': False, 'default_value': False}, | |
| 52 # Explicitly inherits a non-inherited property | |
| 53 {'name': 'HasExplicitlyInheritedProperties', 'field_template': 'monotonic_fl
ag', | |
| 54 'inherited': False, 'independent': False, 'default_value': False}, | |
| 55 # These are set if we used viewport or rem units when resolving a length. | |
| 56 # TODO(shend): HasViewportUnits should be a monotonic_flag. | |
| 57 {'name': 'HasViewportUnits', 'field_template': 'primitive', 'default_value':
'false', | |
| 58 'type_name': 'bool', 'inherited': False, 'independent': False}, | |
| 59 {'name': 'HasRemUnits', 'field_template': 'monotonic_flag', 'default_value':
'false', | |
| 60 'inherited': False, 'independent': False}, | |
| 61 # These properties only have generated storage, and their methods are handwr
itten in ComputedStyle. | |
| 62 # TODO(shend): Remove these fields and delete the 'storage_only' template. | |
| 63 {'name': 'EmptyState', 'field_template': 'storage_only', 'field_size': 1, 'd
efault_value': 'false', | |
| 64 'type_name': 'bool', 'inherited': False, 'independent': False}, | |
| 65 {'name': 'StyleType', 'field_template': 'storage_only', 'field_size': 6, 'de
fault_value': '0', | |
| 66 'type_name': 'PseudoId', 'inherited': False, 'independent': False}, | |
| 67 {'name': 'PseudoBits', 'field_template': 'storage_only', 'field_size': 8, 'd
efault_value': 'kPseudoIdNone', | |
| 68 'type_name': 'PseudoId', 'inherited': False, 'independent': False}, | |
| 69 # True if 'underline solid' is the only text decoration on this element. | |
| 70 {'name': 'HasSimpleUnderline', 'field_template': 'storage_only', 'field_size
': 1, 'default_value': 'false', | |
| 71 'type_name': 'bool', 'inherited': True, 'independent': False}, | |
| 72 # TODO(shend): vertical align is actually a CSS property, but since we don't
support union fields | |
| 73 # which can be either a keyword or Length, this is generated as a nonpropert
y for now. Remove this | |
| 74 # once we can support union fields and groups. | |
| 75 {'name': 'VerticalAlign', 'field_template': 'storage_only', 'field_size': 4,
'default_value': 'EVerticalAlign::kBaseline', | |
| 76 'type_name': 'EVerticalAlign', 'inherited': False, 'independent': False}, | |
| 77 ] | |
| 78 | |
| 79 | |
| 80 class Field(object): | 20 class Field(object): |
| 81 """ | 21 """ |
| 82 The generated ComputedStyle object is made up of a series of Fields. | 22 The generated ComputedStyle object is made up of a series of Fields. |
| 83 Each Field has a name, size, type, etc, and a bunch of attributes to | 23 Each Field has a name, size, type, etc, and a bunch of attributes to |
| 84 determine which methods it will be used in. | 24 determine which methods it will be used in. |
| 85 | 25 |
| 86 A Field also has enough information to use any storage type in C++, such as | 26 A Field also has enough information to use any storage type in C++, such as |
| 87 regular member variables, or more complex storage like vectors or hashmaps. | 27 regular member variables, or more complex storage like vectors or hashmaps. |
| 88 Almost all properties will have at least one Field, often more than one. | 28 Almost all properties will have at least one Field, often more than one. |
| 89 | 29 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 fields = [] | 200 fields = [] |
| 261 for property_ in properties: | 201 for property_ in properties: |
| 262 # Only generate properties that have a field template | 202 # Only generate properties that have a field template |
| 263 if property_['field_template'] is not None: | 203 if property_['field_template'] is not None: |
| 264 # If the property is independent, add the single-bit sized isInherit
ed flag | 204 # If the property is independent, add the single-bit sized isInherit
ed flag |
| 265 # to the list of Fields as well. | 205 # to the list of Fields as well. |
| 266 if property_['independent']: | 206 if property_['independent']: |
| 267 fields.append(_create_inherited_flag_field(property_)) | 207 fields.append(_create_inherited_flag_field(property_)) |
| 268 | 208 |
| 269 # TODO(shend): Get rid of the property/nonproperty field roles. | 209 # 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' | 210 field_role = 'nonproperty' if property_['has_custom_compare_and_copy
'] else 'property' |
| 273 fields.append(_create_field(field_role, property_)) | 211 fields.append(_create_field(field_role, property_)) |
| 274 | 212 |
| 275 return fields | 213 return fields |
| 276 | 214 |
| 277 | 215 |
| 278 def _pack_fields(fields): | 216 def _pack_fields(fields): |
| 279 """ | 217 """ |
| 280 Group a list of fields into buckets to minimise padding. | 218 Group a list of fields into buckets to minimise padding. |
| 281 Returns a list of buckets, where each bucket is a list of Field objects. | 219 Returns a list of buckets, where each bucket is a list of Field objects. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 302 bucket.append(field) | 240 bucket.append(field) |
| 303 added_to_bucket = True | 241 added_to_bucket = True |
| 304 break | 242 break |
| 305 if not added_to_bucket: | 243 if not added_to_bucket: |
| 306 field_buckets.append([field]) | 244 field_buckets.append([field]) |
| 307 | 245 |
| 308 return field_buckets | 246 return field_buckets |
| 309 | 247 |
| 310 | 248 |
| 311 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): | 249 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): |
| 312 def __init__(self, json5_file_path): | 250 def __init__(self, json5_file_paths): |
| 313 super(ComputedStyleBaseWriter, self).__init__(json5_file_path) | 251 # Read CSS properties |
| 252 super(ComputedStyleBaseWriter, self).__init__([json5_file_paths[0]]) |
| 314 | 253 |
| 315 # Ignore shorthand properties | 254 # Ignore shorthand properties |
| 316 for property_ in self._properties.values(): | 255 for property_ in self._properties.values(): |
| 317 if property_['field_template'] is not None: | 256 if property_['field_template'] is not None: |
| 318 assert not property_['longhands'], \ | 257 assert not property_['longhands'], \ |
| 319 "Shorthand '{}' cannot have a field_template.".format(proper
ty_['name']) | 258 "Shorthand '{}' cannot have a field_template.".format(proper
ty_['name']) |
| 320 | 259 |
| 321 css_properties = [value for value in self._properties.values() if not va
lue['longhands']] | 260 css_properties = [value for value in self._properties.values() if not va
lue['longhands']] |
| 322 | 261 |
| 323 for property_ in css_properties: | 262 for property_ in css_properties: |
| 324 # All CSS properties that are generated do not have custom compariso
n and copy logic. | 263 # All CSS properties that are generated do not have custom compariso
n and copy logic. |
| 325 property_['has_custom_compare_and_copy'] = False | 264 property_['has_custom_compare_and_copy'] = False |
| 326 # CSS properties are not allowed to explicitly specify their field_s
ize. | 265 # CSS properties are not allowed to explicitly specify their field_s
ize. |
| 327 property_['field_size'] = None | 266 property_['field_size'] = None |
| 328 | 267 |
| 329 # TODO(shend): Remove this once we move EXTRA_FIELDS to its own JSON fil
e, | 268 # Read extra fields using the parameter specification from the CSS prope
rties file. |
| 330 # since the JSON5 reader will handle missing fields and defaults. | 269 extra_fields = json5_generator.Json5File.load_from_files( |
| 331 for property_ in EXTRA_FIELDS: | 270 [json5_file_paths[1]], |
| 332 for parameter in self.json5_file.parameters: | 271 default_parameters=self.json5_file.parameters |
| 333 if parameter not in property_: | 272 ).name_dictionaries |
| 334 property_[parameter] = None | |
| 335 | 273 |
| 336 for property_ in EXTRA_FIELDS: | 274 for property_ in extra_fields: |
| 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_) | 275 make_style_builder.apply_property_naming_defaults(property_) |
| 341 | 276 |
| 342 all_properties = css_properties + EXTRA_FIELDS | 277 all_properties = css_properties + extra_fields |
| 343 | 278 |
| 344 # Override the type name when field_type_path is specified | 279 # Override the type name when field_type_path is specified |
| 345 for property_ in all_properties: | 280 for property_ in all_properties: |
| 346 if property_['field_type_path']: | 281 if property_['field_type_path']: |
| 347 property_['type_name'] = property_['field_type_path'].split('/')
[-1] | 282 property_['type_name'] = property_['field_type_path'].split('/')
[-1] |
| 348 | 283 |
| 349 self._generated_enums = _create_enums(all_properties) | 284 self._generated_enums = _create_enums(all_properties) |
| 350 | 285 |
| 351 all_fields = _create_fields(all_properties) | 286 all_fields = _create_fields(all_properties) |
| 352 | 287 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 348 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
| 414 def generate_base_computed_style_constants(self): | 349 def generate_base_computed_style_constants(self): |
| 415 return { | 350 return { |
| 416 'properties': self._properties, | 351 'properties': self._properties, |
| 417 'enums': self._generated_enums, | 352 'enums': self._generated_enums, |
| 418 'fields': self._fields, | 353 'fields': self._fields, |
| 419 } | 354 } |
| 420 | 355 |
| 421 if __name__ == '__main__': | 356 if __name__ == '__main__': |
| 422 json5_generator.Maker(ComputedStyleBaseWriter).main() | 357 json5_generator.Maker(ComputedStyleBaseWriter).main() |
| OLD | NEW |