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 |