Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: third_party/WebKit/Source/build/scripts/make_computed_style_base.py

Issue 2786883002: Generate subgroup StyleSurroundData in ComputedStyle. (Closed)
Patch Set: Fix things Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 class_name, join_name
16 ) 16 )
17 from collections import OrderedDict 17 from collections import defaultdict, OrderedDict
18 from itertools import chain
18 19
20 # TODO(shend): Improve documentation and add docstrings.
19 21
20 # Temporary hard-coded list of extra fields. 22 # Temporary hard-coded list of extra fields.
21 # TODO(shend): Put this into its own JSON5 file. 23 # TODO(shend): Put this into its own JSON5 file.
22 EXTRA_FIELDS = [ 24 EXTRA_FIELDS = [
23 {'name': 'IsLink', 'field_template': 'monotonic_flag', 25 {'name': 'IsLink', 'field_template': 'monotonic_flag',
24 'inherited': False, 'independent': False, 'default_value': False}, 26 'inherited': False, 'independent': False, 'default_value': False},
25 {'name': 'OriginalDisplay', 'field_template': 'keyword', 'default_value': 'i nline', 27 {'name': 'OriginalDisplay', 'field_template': 'keyword', 'default_value': 'i nline',
26 'type_name': 'EDisplay', 'inherited': False, 'independent': False, 28 'type_name': 'EDisplay', 'inherited': False, 'independent': False,
27 'keywords': [ 29 'keywords': [
28 "inline", "block", "list-item", "inline-block", "table", "inline-table" , "table-row-group", "table-header-group", 30 "inline", "block", "list-item", "inline-block", "table", "inline-table" , "table-row-group", "table-header-group",
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 {'name': 'PseudoBits', 'field_template': 'storage_only', 'field_size': 8, 'd efault_value': 'kPseudoIdNone', 69 {'name': 'PseudoBits', 'field_template': 'storage_only', 'field_size': 8, 'd efault_value': 'kPseudoIdNone',
68 'type_name': 'PseudoId', 'inherited': False, 'independent': False}, 70 'type_name': 'PseudoId', 'inherited': False, 'independent': False},
69 # True if 'underline solid' is the only text decoration on this element. 71 # 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', 72 {'name': 'HasSimpleUnderline', 'field_template': 'storage_only', 'field_size ': 1, 'default_value': 'false',
71 'type_name': 'bool', 'inherited': True, 'independent': False}, 73 '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 74 # 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 75 # 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. 76 # once we can support union fields and groups.
75 {'name': 'VerticalAlign', 'field_template': 'storage_only', 'field_size': 4, 'default_value': 'EVerticalAlign::kBaseline', 77 {'name': 'VerticalAlign', 'field_template': 'storage_only', 'field_size': 4, 'default_value': 'EVerticalAlign::kBaseline',
76 'type_name': 'EVerticalAlign', 'inherited': False, 'independent': False}, 78 'type_name': 'EVerticalAlign', 'inherited': False, 'independent': False},
79 # Fields that are shared by multiple properties.
80 # TODO(shend): Try to split these up to one field per property.
81 {'name': 'margin', 'field_template': 'storage_only', 'field_size': None, 'fi eld_type_path': 'platform/LengthBox',
82 'type_name': 'LengthBox', 'field_group': 'surround', 'default_value': 'Leng thBox(kFixed)', 'inherited': False,
83 'independent': False, 'has_custom_compare_and_copy': False},
84 {'name': 'padding', 'field_template': 'storage_only', 'field_size': None, 'f ield_type_path': 'platform/LengthBox',
85 'type_name': 'LengthBox', 'field_group': 'surround', 'default_value': 'Leng thBox(kFixed)', 'inherited': False,
86 'independent': False, 'has_custom_compare_and_copy': False},
87 {'name': 'border', 'field_template': 'storage_only', 'field_size': None, 'fi eld_type_path': 'core/style/BorderData',
88 'type_name': 'BorderData', 'field_group': 'surround', 'default_value': 'Bor derData()', 'inherited': False,
89 'independent': False, 'has_custom_compare_and_copy': False},
77 ] 90 ]
78 91
79 92
93 def _flatten_list(x):
94 """Flattens a list of lists into a single list."""
95 return list(chain.from_iterable(x))
96
97
98 def _num_32_bit_words_for_bit_fields(bit_fields):
99 """Gets the number of 32 bit unsigned integers needed store a list of bit fi elds."""
100 num_buckets, cur_bucket = 0, 0
101 for field in bit_fields:
102 if field.size + cur_bucket > 32:
103 num_buckets += 1
104 cur_bucket = 0
105 cur_bucket += field.size
106 return num_buckets + (cur_bucket > 0)
107
108
109 class Group(object):
110 """Represents a group of fields stored together in a class.
111
112 Attributes:
113 name: The name of the group as a string.
114 subgroups: List of Group instances that are stored as subgroups under th is group.
115 fields: List of Field instances stored directly under this group.
116 """
117 def __init__(self, name, subgroups, fields):
118 self.name = name
119 self.subgroups = subgroups
120 self.fields = fields
121 self.type_name = class_name(join_name('style', name, ' data'))
122 self.member_name = class_member_name(name)
123 self.num_32_bit_words_for_bit_fields = _num_32_bit_words_for_bit_fields(
124 field for field in fields if field.is_bit_field
125 )
126
127 # Recursively get all the fields in the subgroups as well
128 self.all_fields = _flatten_list(subgroup.all_fields for subgroup in subg roups) + fields
129
130
80 class Field(object): 131 class Field(object):
81 """ 132 """
82 The generated ComputedStyle object is made up of a series of Fields. 133 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 134 Each Field has a name, size, type, etc, and a bunch of attributes to
84 determine which methods it will be used in. 135 determine which methods it will be used in.
85 136
86 A Field also has enough information to use any storage type in C++, such as 137 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. 138 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. 139 Almost all properties will have at least one Field, often more than one.
89 140
90 Most attributes in this class correspond to parameters in CSSProperties.json 5. 141 Most attributes in this class correspond to parameters in CSSProperties.json 5.
91 See that file for a more detailed explanation of each attribute. 142 See that file for a more detailed explanation of each attribute.
92 143
93 Attributes: 144 Attributes:
94 field_role: The semantic role of the field. Can be: 145 field_role: The semantic role of the field. Can be:
95 - 'property': for fields that store CSS properties 146 - 'property': for fields that store CSS properties
96 - 'inherited_flag': for single-bit flags that store whether a proper ty is 147 - 'inherited_flag': for single-bit flags that store whether a proper ty is
97 inherited by this style or set explicitly 148 inherited by this style or set explicitly
98 - 'nonproperty': for fields that are not CSS properties 149 - 'nonproperty': for fields that are not CSS properties
99 name_for_methods: String used to form the names of getters and setters. 150 name_for_methods: String used to form the names of getters and setters.
100 Should be in upper camel case. 151 Should be in upper camel case.
101 property_name: Name of the property that the field is part of. 152 property_name: Name of the property that the field is part of.
102 type_name: Name of the C++ type exposed by the generated interface (e.g. EClear, int). 153 type_name: Name of the C++ type exposed by the generated interface (e.g. EClear, int).
103 field_template: Determines the interface generated for the field. Can be one of: 154 field_template: Determines the interface generated for the field. Can be one of:
104 keyword, flag, or monotonic_flag. 155 keyword, flag, or monotonic_flag.
156 group_member_name: The class member name representing the group.
meade_UTC10 2017/04/20 03:08:40 This is the first time you mention groups in this
shend 2017/04/20 03:22:34 Clarified the comment.
105 size: Number of bits needed for storage. 157 size: Number of bits needed for storage.
106 default_value: Default value for this field when it is first initialized . 158 default_value: Default value for this field when it is first initialized .
107 """ 159 """
108 160
109 def __init__(self, field_role, name_for_methods, property_name, type_name, 161 def __init__(self, field_role, name_for_methods, property_name, type_name,
110 field_template, size, default_value, getter_method_name, setter _method_name, 162 field_template, field_group, size, default_value,
111 initial_method_name, **kwargs): 163 getter_method_name, setter_method_name, initial_method_name, ** kwargs):
112 """Creates a new field.""" 164 """Creates a new field."""
113 self.name = class_member_name(name_for_methods) 165 self.name = class_member_name(name_for_methods)
114 self.property_name = property_name 166 self.property_name = property_name
115 self.type_name = type_name 167 self.type_name = type_name
116 self.field_template = field_template 168 self.field_template = field_template
169 self.group_member_name = class_member_name(field_group) if field_group e lse None
117 self.size = size 170 self.size = size
118 self.default_value = default_value 171 self.default_value = default_value
119 172
120 # Field role: one of these must be true 173 # Field role: one of these must be true
121 self.is_property = field_role == 'property' 174 self.is_property = field_role == 'property'
122 self.is_inherited_flag = field_role == 'inherited_flag' 175 self.is_inherited_flag = field_role == 'inherited_flag'
123 self.is_nonproperty = field_role == 'nonproperty' 176 self.is_nonproperty = field_role == 'nonproperty'
124 assert (self.is_property, self.is_inherited_flag, self.is_nonproperty).c ount(True) == 1, \ 177 assert (self.is_property, self.is_inherited_flag, self.is_nonproperty).c ount(True) == 1, \
125 'Field role has to be exactly one of: property, inherited_flag, nonp roperty' 178 'Field role has to be exactly one of: property, inherited_flag, nonp roperty'
126 179
(...skipping 20 matching lines...) Expand all
147 """ 200 """
148 Get a list of paths that need to be included for ComputedStyleBase. 201 Get a list of paths that need to be included for ComputedStyleBase.
149 """ 202 """
150 include_paths = set() 203 include_paths = set()
151 for property_ in properties: 204 for property_ in properties:
152 if property_['field_type_path'] is not None: 205 if property_['field_type_path'] is not None:
153 include_paths.add(property_['field_type_path'] + '.h') 206 include_paths.add(property_['field_type_path'] + '.h')
154 return list(sorted(include_paths)) 207 return list(sorted(include_paths))
155 208
156 209
210 def _group_fields(fields):
211 """Groups a list of fields by their group_member_name and returns the root g roup."""
212 groups = defaultdict(list)
213 for field in fields:
214 groups[field.group_member_name].append(field)
215
216 no_group = groups.pop(None)
217 subgroups = [Group(group_member_name, [], _reorder_fields(fields)) for group _member_name, fields in groups.items()]
218 return Group('', subgroups=subgroups, fields=_reorder_fields(no_group))
219
220
157 def _create_enums(properties): 221 def _create_enums(properties):
158 """ 222 """
159 Returns an OrderedDict of enums to be generated, enum name -> [list of enum values] 223 Returns an OrderedDict of enums to be generated, enum name -> [list of enum values]
160 """ 224 """
161 enums = {} 225 enums = {}
162 for property_ in properties: 226 for property_ in properties:
163 # Only generate enums for keyword properties that use the default field_ type_path. 227 # Only generate enums for keyword properties that use the default field_ type_path.
164 if property_['field_template'] == 'keyword' and property_['field_type_pa th'] is None: 228 if property_['field_template'] == 'keyword' and property_['field_type_pa th'] is None:
165 enum_name = property_['type_name'] 229 enum_name = property_['type_name']
166 enum_values = [enum_value_name(k) for k in property_['keywords']] 230 enum_values = [enum_value_name(k) for k in property_['keywords']]
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 size = 1 278 size = 1
215 279
216 return Field( 280 return Field(
217 field_role, 281 field_role,
218 name_for_methods, 282 name_for_methods,
219 property_name=property_['name'], 283 property_name=property_['name'],
220 inherited=property_['inherited'], 284 inherited=property_['inherited'],
221 independent=property_['independent'], 285 independent=property_['independent'],
222 type_name=type_name, 286 type_name=type_name,
223 field_template=property_['field_template'], 287 field_template=property_['field_template'],
288 field_group=property_['field_group'],
224 size=size, 289 size=size,
225 default_value=default_value, 290 default_value=default_value,
226 getter_method_name=property_['getter'], 291 getter_method_name=property_['getter'],
227 setter_method_name=property_['setter'], 292 setter_method_name=property_['setter'],
228 initial_method_name=property_['initial'], 293 initial_method_name=property_['initial'],
229 ) 294 )
230 295
231 296
232 def _create_inherited_flag_field(property_): 297 def _create_inherited_flag_field(property_):
233 """ 298 """
234 Create the field used for an inheritance fast path from an independent CSS p roperty, 299 Create the field used for an inheritance fast path from an independent CSS p roperty,
235 and return the Field object. 300 and return the Field object.
236 """ 301 """
237 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') 302 name_for_methods = join_name(property_['name_for_methods'], 'is inherited')
238 return Field( 303 return Field(
239 'inherited_flag', 304 'inherited_flag',
240 name_for_methods, 305 name_for_methods,
241 property_name=property_['name'], 306 property_name=property_['name'],
242 type_name='bool', 307 type_name='bool',
243 field_template='primitive', 308 field_template='primitive',
309 field_group=property_['field_group'],
244 size=1, 310 size=1,
245 default_value='true', 311 default_value='true',
246 getter_method_name=method_name(name_for_methods), 312 getter_method_name=method_name(name_for_methods),
247 setter_method_name=method_name(join_name('set', name_for_methods)), 313 setter_method_name=method_name(join_name('set', name_for_methods)),
248 initial_method_name=method_name(join_name('initial', name_for_methods)), 314 initial_method_name=method_name(join_name('initial', name_for_methods)),
249 ) 315 )
250 316
251 317
252 def _create_fields(properties): 318 def _create_fields(properties):
253 """ 319 """
(...skipping 10 matching lines...) Expand all
264 330
265 # TODO(shend): Get rid of the property/nonproperty field roles. 331 # 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 332 # If the field has_custom_compare_and_copy, then it does not appear in
267 # ComputedStyle::operator== and ComputedStyle::CopyNonInheritedFromC ached. 333 # ComputedStyle::operator== and ComputedStyle::CopyNonInheritedFromC ached.
268 field_role = 'nonproperty' if property_['has_custom_compare_and_copy '] else 'property' 334 field_role = 'nonproperty' if property_['has_custom_compare_and_copy '] else 'property'
269 fields.append(_create_field(field_role, property_)) 335 fields.append(_create_field(field_role, property_))
270 336
271 return fields 337 return fields
272 338
273 339
274 def _pack_fields(fields): 340 def _reorder_fields(fields):
275 """ 341 """
276 Group a list of fields into buckets to minimise padding. 342 Returns a list of fields ordered to minimise padding.
277 Returns a list of buckets, where each bucket is a list of Field objects.
278 """ 343 """
344 # Separate out bit fields from normal fields
345 bit_fields = [field for field in fields if field.is_bit_field]
346 normal_fields = [field for field in fields if not field.is_bit_field]
meade_UTC10 2017/04/20 03:08:40 normal -> fields that are some type other than a b
shend 2017/04/20 03:22:34 Changed to non_bit_fields.
347
279 # Since fields cannot cross word boundaries, in order to minimize 348 # Since fields cannot cross word boundaries, in order to minimize
280 # padding, group fields into buckets so that as many buckets as possible 349 # padding, group fields into buckets so that as many buckets as possible
281 # are exactly 32 bits. Although this greedy approach may not always 350 # are exactly 32 bits. Although this greedy approach may not always
282 # produce the optimal solution, we add a static_assert to the code to 351 # produce the optimal solution, we add a static_assert to the code to
283 # ensure ComputedStyleBase results in the expected size. If that 352 # ensure ComputedStyleBase results in the expected size. If that
284 # static_assert fails, this code is falling into the small number of 353 # static_assert fails, this code is falling into the small number of
285 # cases that are suboptimal, and may need to be rethought. 354 # cases that are suboptimal, and may need to be rethought.
286 # For more details on packing bit fields to reduce padding, see: 355 # For more details on packing bit fields to reduce padding, see:
287 # http://www.catb.org/esr/structure-packing/#_bitfields 356 # http://www.catb.org/esr/structure-packing/#_bitfields
288 field_buckets = [] 357 field_buckets = []
289 # Consider fields in descending order of size to reduce fragmentation 358 # Consider fields in descending order of size to reduce fragmentation
290 # when they are selected. Ties broken in alphabetical order by name. 359 # when they are selected. Ties broken in alphabetical order by name.
291 for field in sorted(fields, key=lambda f: (-f.size, f.name)): 360 for field in sorted(bit_fields, key=lambda f: (-f.size, f.name)):
292 added_to_bucket = False 361 added_to_bucket = False
293 # Go through each bucket and add this field if it will not increase 362 # Go through each bucket and add this field if it will not increase
294 # the bucket's size to larger than 32 bits. Otherwise, make a new 363 # the bucket's size to larger than 32 bits. Otherwise, make a new
295 # bucket containing only this field. 364 # bucket containing only this field.
296 for bucket in field_buckets: 365 for bucket in field_buckets:
297 if sum(f.size for f in bucket) + field.size <= 32: 366 if sum(f.size for f in bucket) + field.size <= 32:
298 bucket.append(field) 367 bucket.append(field)
299 added_to_bucket = True 368 added_to_bucket = True
300 break 369 break
301 if not added_to_bucket: 370 if not added_to_bucket:
302 field_buckets.append([field]) 371 field_buckets.append([field])
303 372
304 return field_buckets 373 # Normal fields go first, then the bit fields.
374 return list(normal_fields) + _flatten_list(field_buckets)
305 375
306 376
307 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): 377 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter):
308 def __init__(self, json5_file_path): 378 def __init__(self, json5_file_path):
309 super(ComputedStyleBaseWriter, self).__init__(json5_file_path) 379 super(ComputedStyleBaseWriter, self).__init__(json5_file_path)
310 380
311 # Ignore shorthand properties 381 # Ignore shorthand properties
312 for property_ in self._properties.values(): 382 for property_ in self._properties.values():
313 if property_['field_template'] is not None: 383 if property_['field_template'] is not None:
314 assert not property_['longhands'], \ 384 assert not property_['longhands'], \
315 "Shorthand '{}' cannot have a field_template.".format(proper ty_['name']) 385 "Shorthand '{}' cannot have a field_template.".format(proper ty_['name'])
316 386
317 css_properties = [value for value in self._properties.values() if not va lue['longhands']] 387 css_properties = [value for value in self._properties.values() if not va lue['longhands']]
318 388
319 for property_ in css_properties: 389 for property_ in css_properties:
320 # All CSS properties that are generated do not have custom compariso n and copy logic. 390 # All CSS properties that are generated do not have custom compariso n and copy logic.
321 property_['has_custom_compare_and_copy'] = False 391 property_['has_custom_compare_and_copy'] = False
322 # CSS properties are not allowed to explicitly specify their field_s ize. 392 # CSS properties are not allowed to explicitly specify their field_s ize.
323 property_['field_size'] = None 393 property_['field_size'] = None
324 394
325 # TODO(shend): Remove this once we move EXTRA_FIELDS to its own JSON fil e, 395 # TODO(shend): Remove this once we move EXTRA_FIELDS to its own JSON fil e,
326 # since the JSON5 reader will handle missing fields and defaults. 396 # since the JSON5 reader will handle missing fields and defaults.
327 # TODO(shend): Remove this once we move NONPROPERTIES to its own JSON fi le,
328 # since the JSON5 reader will handle missing fields and defaults.
329 for property_ in EXTRA_FIELDS: 397 for property_ in EXTRA_FIELDS:
330 for parameter in self.json5_file.parameters: 398 for parameter in self.json5_file.parameters:
331 if parameter not in property_: 399 if parameter not in property_:
332 property_[parameter] = None 400 property_[parameter] = None
333 401
334 for property_ in EXTRA_FIELDS: 402 for property_ in EXTRA_FIELDS:
335 # TODO(shend): Remove the line below once we move EXTRA_FIELDS to it s 403 # TODO(shend): Remove the line below once we move EXTRA_FIELDS to it s
336 # own file which would enforce defaults. 404 # own file which would enforce defaults.
337 property_['has_custom_compare_and_copy'] = True 405 if 'has_custom_compare_and_copy' not in property_:
406 property_['has_custom_compare_and_copy'] = True
338 make_style_builder.apply_property_naming_defaults(property_) 407 make_style_builder.apply_property_naming_defaults(property_)
339 408
340 all_properties = css_properties + EXTRA_FIELDS 409 all_properties = css_properties + EXTRA_FIELDS
341 410
342 # Override the type name when field_type_path is specified 411 # Override the type name when field_type_path is specified
343 for property_ in all_properties: 412 for property_ in all_properties:
344 if property_['field_type_path']: 413 if property_['field_type_path']:
345 property_['type_name'] = property_['field_type_path'].split('/') [-1] 414 property_['type_name'] = property_['field_type_path'].split('/') [-1]
346 415
347 self._generated_enums = _create_enums(all_properties) 416 self._generated_enums = _create_enums(all_properties)
348 417
349 all_fields = _create_fields(all_properties) 418 all_fields = _create_fields(all_properties)
350 419
351 # Separate the normal fields from the bit fields 420 # Organise fields into a tree structure where the root group
352 bit_fields = [field for field in all_fields if field.is_bit_field] 421 # is ComputedStyleBase.
353 normal_fields = [field for field in all_fields if not field.is_bit_field ] 422 self._root_group = _group_fields(all_fields)
354
355 # Pack bit fields into buckets
356 field_buckets = _pack_fields(bit_fields)
357
358 # The expected size of ComputedStyleBase is equivalent to as many words
359 # as the total number of buckets.
360 self._expected_bit_field_bytes = len(field_buckets)
361
362 # The most optimal size of ComputedStyleBase is the total sum of all the
363 # field sizes, rounded up to the nearest word. If this produces the
364 # incorrect value, either the packing algorithm is not optimal or there
365 # is no way to pack the fields such that excess padding space is not
366 # added.
367 # If this fails, increase extra_padding_bytes by 1, but be aware that
368 # this also increases ComputedStyleBase by 1 word.
369 # We should be able to bring extra_padding_bytes back to 0 from time to
370 # time.
371 extra_padding_bytes = 0
372 optimal_bit_field_bytes = int(math.ceil(sum(f.size for f in bit_fields) / 32.0))
373 real_bit_field_bytes = optimal_bit_field_bytes + extra_padding_bytes
374 assert self._expected_bit_field_bytes == real_bit_field_bytes, \
375 ('The field packing algorithm produced %s bytes, optimal is %s bytes ' %
376 (self._expected_bit_field_bytes, real_bit_field_bytes))
377
378 # Normal fields go first, then the bit fields.
379 self._fields = list(normal_fields)
380
381 # Order the fields so fields in each bucket are adjacent.
382 for bucket in field_buckets:
383 for field in bucket:
384 self._fields.append(field)
385 423
386 self._include_paths = _get_include_paths(all_properties) 424 self._include_paths = _get_include_paths(all_properties)
387 self._outputs = { 425 self._outputs = {
388 'ComputedStyleBase.h': self.generate_base_computed_style_h, 426 'ComputedStyleBase.h': self.generate_base_computed_style_h,
389 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp, 427 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp,
390 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co nstants, 428 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co nstants,
391 } 429 }
392 430
393 @template_expander.use_jinja('ComputedStyleBase.h.tmpl') 431 @template_expander.use_jinja('ComputedStyleBase.h.tmpl')
394 def generate_base_computed_style_h(self): 432 def generate_base_computed_style_h(self):
395 return { 433 return {
396 'properties': self._properties, 434 'properties': self._properties,
397 'enums': self._generated_enums, 435 'enums': self._generated_enums,
398 'include_paths': self._include_paths, 436 'include_paths': self._include_paths,
399 'fields': self._fields, 437 'computed_style': self._root_group,
400 } 438 }
401 439
402 @template_expander.use_jinja('ComputedStyleBase.cpp.tmpl') 440 @template_expander.use_jinja('ComputedStyleBase.cpp.tmpl')
403 def generate_base_computed_style_cpp(self): 441 def generate_base_computed_style_cpp(self):
404 return { 442 return {
405 'properties': self._properties, 443 'properties': self._properties,
406 'enums': self._generated_enums, 444 'enums': self._generated_enums,
407 'fields': self._fields, 445 'computed_style': self._root_group,
408 'expected_bit_field_bytes': self._expected_bit_field_bytes,
409 } 446 }
410 447
411 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') 448 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl')
412 def generate_base_computed_style_constants(self): 449 def generate_base_computed_style_constants(self):
413 return { 450 return {
414 'properties': self._properties, 451 'properties': self._properties,
415 'enums': self._generated_enums, 452 'enums': self._generated_enums,
416 'fields': self._fields,
417 } 453 }
418 454
419 if __name__ == '__main__': 455 if __name__ == '__main__':
420 json5_generator.Maker(ComputedStyleBaseWriter).main() 456 json5_generator.Maker(ComputedStyleBaseWriter).main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698