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 |
18 | |
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 | 18 |
79 | 19 |
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. |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 fields = [] | 196 fields = [] |
257 for property_ in properties: | 197 for property_ in properties: |
258 # Only generate properties that have a field template | 198 # Only generate properties that have a field template |
259 if property_['field_template'] is not None: | 199 if property_['field_template'] is not None: |
260 # If the property is independent, add the single-bit sized isInherit
ed flag | 200 # If the property is independent, add the single-bit sized isInherit
ed flag |
261 # to the list of Fields as well. | 201 # to the list of Fields as well. |
262 if property_['independent']: | 202 if property_['independent']: |
263 fields.append(_create_inherited_flag_field(property_)) | 203 fields.append(_create_inherited_flag_field(property_)) |
264 | 204 |
265 # TODO(shend): Get rid of the property/nonproperty field roles. | 205 # 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' | 206 field_role = 'nonproperty' if property_['has_custom_compare_and_copy
'] else 'property' |
269 fields.append(_create_field(field_role, property_)) | 207 fields.append(_create_field(field_role, property_)) |
270 | 208 |
271 return fields | 209 return fields |
272 | 210 |
273 | 211 |
274 def _pack_fields(fields): | 212 def _pack_fields(fields): |
275 """ | 213 """ |
276 Group a list of fields into buckets to minimise padding. | 214 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. | 215 Returns a list of buckets, where each bucket is a list of Field objects. |
(...skipping 20 matching lines...) Expand all Loading... |
298 bucket.append(field) | 236 bucket.append(field) |
299 added_to_bucket = True | 237 added_to_bucket = True |
300 break | 238 break |
301 if not added_to_bucket: | 239 if not added_to_bucket: |
302 field_buckets.append([field]) | 240 field_buckets.append([field]) |
303 | 241 |
304 return field_buckets | 242 return field_buckets |
305 | 243 |
306 | 244 |
307 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): | 245 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): |
308 def __init__(self, json5_file_path): | 246 def __init__(self, json5_file_paths): |
309 super(ComputedStyleBaseWriter, self).__init__(json5_file_path) | 247 # Read CSS properties |
| 248 super(ComputedStyleBaseWriter, self).__init__([json5_file_paths[0]]) |
310 | 249 |
311 # Ignore shorthand properties | 250 # Ignore shorthand properties |
312 for property_ in self._properties.values(): | 251 for property_ in self._properties.values(): |
313 if property_['field_template'] is not None: | 252 if property_['field_template'] is not None: |
314 assert not property_['longhands'], \ | 253 assert not property_['longhands'], \ |
315 "Shorthand '{}' cannot have a field_template.".format(proper
ty_['name']) | 254 "Shorthand '{}' cannot have a field_template.".format(proper
ty_['name']) |
316 | 255 |
317 css_properties = [value for value in self._properties.values() if not va
lue['longhands']] | 256 css_properties = [value for value in self._properties.values() if not va
lue['longhands']] |
318 | 257 |
319 for property_ in css_properties: | 258 for property_ in css_properties: |
320 # All CSS properties have generated comparison and copy. | 259 # All CSS properties have generated comparison and copy. |
321 property_['has_custom_compare_and_copy'] = False | 260 property_['has_custom_compare_and_copy'] = False |
322 # CSS properties are not allowed to explicitly specify their field_s
ize. | 261 # CSS properties are not allowed to explicitly specify their field_s
ize. |
323 property_['field_size'] = None | 262 property_['field_size'] = None |
324 | 263 |
325 # TODO(shend): Remove this once we move EXTRA_FIELDS to its own JSON fil
e, | 264 # Read extra fields using the parameter specification from the CSS prope
rties file. |
326 # since the JSON5 reader will handle missing fields and defaults. | 265 extra_fields = json5_generator.Json5File.load_from_files( |
327 extra_fields = [defaultdict(lambda: None, item) for item in EXTRA_FIELDS
] | 266 [json5_file_paths[1]], |
| 267 default_parameters=self.json5_file.parameters |
| 268 ).name_dictionaries |
328 | 269 |
329 for property_ in extra_fields: | 270 for property_ in extra_fields: |
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_) | 271 self._apply_property_naming_defaults(property_) |
334 | 272 |
335 all_properties = css_properties + extra_fields | 273 all_properties = css_properties + extra_fields |
336 | 274 |
337 # Override the type name when field_type_path is specified | 275 # Override the type name when field_type_path is specified |
338 for property_ in all_properties: | 276 for property_ in all_properties: |
339 if property_['field_type_path']: | 277 if property_['field_type_path']: |
340 property_['type_name'] = property_['field_type_path'].split('/')
[-1] | 278 property_['type_name'] = property_['field_type_path'].split('/')
[-1] |
341 | 279 |
342 self._generated_enums = _create_enums(all_properties) | 280 self._generated_enums = _create_enums(all_properties) |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 344 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
407 def generate_base_computed_style_constants(self): | 345 def generate_base_computed_style_constants(self): |
408 return { | 346 return { |
409 'properties': self._properties, | 347 'properties': self._properties, |
410 'enums': self._generated_enums, | 348 'enums': self._generated_enums, |
411 'fields': self._fields, | 349 'fields': self._fields, |
412 } | 350 } |
413 | 351 |
414 if __name__ == '__main__': | 352 if __name__ == '__main__': |
415 json5_generator.Maker(ComputedStyleBaseWriter).main() | 353 json5_generator.Maker(ComputedStyleBaseWriter).main() |
OLD | NEW |