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 |