Chromium Code Reviews| 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 class_name, join_name |
| 16 ) | 16 ) |
| 17 from collections import OrderedDict | 17 from collections import defaultdict, OrderedDict |
| 18 from itertools import chain | |
| 18 | 19 |
| 19 | 20 |
| 20 # Temporary hard-coded list of fields that are not CSS properties. | 21 # Temporary hard-coded list of fields that are not CSS properties. |
| 21 # TODO(shend): Put this into its own JSON5 file. | 22 # TODO(shend): Put this into its own JSON5 file. |
| 22 NONPROPERTIES = [ | 23 NONPROPERTIES = [ |
| 23 {'name': 'IsLink', 'field_template': 'monotonic_flag', | 24 {'name': 'IsLink', 'field_template': 'monotonic_flag', |
| 24 'inherited': False, 'independent': False, 'default_value': False}, | 25 'inherited': False, 'independent': False, 'default_value': False}, |
| 25 {'name': 'OriginalDisplay', 'field_template': 'keyword', 'default_value': 'i nline', | 26 {'name': 'OriginalDisplay', 'field_template': 'keyword', 'default_value': 'i nline', |
| 26 'type_name': 'EDisplay', 'inherited': False, 'independent': False, | 27 'type_name': 'EDisplay', 'inherited': False, 'independent': False, |
| 27 'keywords': [ | 28 'keywords': [ |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 62 {'name': 'HasSimpleUnderline', 'field_template': 'storage_only', 'field_size ': 1, 'default_value': 'false', | 63 {'name': 'HasSimpleUnderline', 'field_template': 'storage_only', 'field_size ': 1, 'default_value': 'false', |
| 63 'type_name': 'bool', 'inherited': True, 'independent': False}, | 64 'type_name': 'bool', 'inherited': True, 'independent': False}, |
| 64 # TODO(shend): vertical align is actually a CSS property, but since we don't support union fields | 65 # TODO(shend): vertical align is actually a CSS property, but since we don't support union fields |
| 65 # which can be either a keyword or Length, this is generated as a nonpropert y for now. Remove this | 66 # which can be either a keyword or Length, this is generated as a nonpropert y for now. Remove this |
| 66 # once we can support union fields and groups. | 67 # once we can support union fields and groups. |
| 67 {'name': 'VerticalAlign', 'field_template': 'storage_only', 'field_size': 4, 'default_value': 'EVerticalAlign::kBaseline', | 68 {'name': 'VerticalAlign', 'field_template': 'storage_only', 'field_size': 4, 'default_value': 'EVerticalAlign::kBaseline', |
| 68 'type_name': 'EVerticalAlign', 'inherited': False, 'independent': False}, | 69 'type_name': 'EVerticalAlign', 'inherited': False, 'independent': False}, |
| 69 ] | 70 ] |
| 70 | 71 |
| 71 | 72 |
| 73 def _flatten_list(x): | |
| 74 """Flattens a list of lists into a single list.""" | |
| 75 return list(chain.from_iterable(x)) | |
| 76 | |
| 77 | |
| 78 def _num_bit_field_buckets(bit_fields): | |
|
meade_UTC10
2017/04/06 03:29:57
would this be better as something like
_num_32_bi
shend
2017/04/06 04:39:39
Done.
| |
| 79 """Gets the number of 32 bit unsigned integers needed store a list of bit fi elds.""" | |
| 80 num_buckets, cur_bucket = 0, 0 | |
| 81 for field in bit_fields: | |
| 82 if field.size + cur_bucket > 32: | |
| 83 num_buckets += 1 | |
| 84 cur_bucket = 0 | |
| 85 cur_bucket += field.size | |
| 86 return num_buckets + (cur_bucket > 0) | |
| 87 | |
| 88 | |
| 89 class Group(object): | |
| 90 def __init__(self, name, subgroups, fields): | |
| 91 """Represents a group of fields, which may contain subgroups that are dy namically allocated.""" | |
|
meade_UTC10
2017/04/06 03:29:57
Could you please document the types of the paramet
shend
2017/04/06 04:39:39
Agreed, the documentation in this file could be si
| |
| 92 self.name = name | |
| 93 self.subgroups = subgroups | |
| 94 self.fields = fields | |
| 95 self.type_name = class_name(join_name('style', name, ' data')) | |
| 96 self.member_name = class_member_name(name) | |
| 97 self.num_bit_field_buckets = _num_bit_field_buckets(field for field in f ields if field.is_bit_field) | |
| 98 | |
| 99 # Recursively get all the fields in the subgroups as well | |
| 100 self.all_fields = _flatten_list(subgroup.all_fields for subgroup in subg roups) + fields | |
| 101 | |
| 102 | |
| 72 class Field(object): | 103 class Field(object): |
| 73 """ | 104 """ |
| 74 The generated ComputedStyle object is made up of a series of Fields. | 105 The generated ComputedStyle object is made up of a series of Fields. |
| 75 Each Field has a name, size, type, etc, and a bunch of attributes to | 106 Each Field has a name, size, type, etc, and a bunch of attributes to |
| 76 determine which methods it will be used in. | 107 determine which methods it will be used in. |
| 77 | 108 |
| 78 A Field also has enough information to use any storage type in C++, such as | 109 A Field also has enough information to use any storage type in C++, such as |
| 79 regular member variables, or more complex storage like vectors or hashmaps. | 110 regular member variables, or more complex storage like vectors or hashmaps. |
| 80 Almost all properties will have at least one Field, often more than one. | 111 Almost all properties will have at least one Field, often more than one. |
| 81 | 112 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 92 Should be in upper camel case. | 123 Should be in upper camel case. |
| 93 property_name: Name of the property that the field is part of. | 124 property_name: Name of the property that the field is part of. |
| 94 type_name: Name of the C++ type exposed by the generated interface (e.g. EClear, int). | 125 type_name: Name of the C++ type exposed by the generated interface (e.g. EClear, int). |
| 95 field_template: Determines the interface generated for the field. Can be one of: | 126 field_template: Determines the interface generated for the field. Can be one of: |
| 96 keyword, flag, or monotonic_flag. | 127 keyword, flag, or monotonic_flag. |
| 97 size: Number of bits needed for storage. | 128 size: Number of bits needed for storage. |
| 98 default_value: Default value for this field when it is first initialized . | 129 default_value: Default value for this field when it is first initialized . |
| 99 """ | 130 """ |
| 100 | 131 |
| 101 def __init__(self, field_role, name_for_methods, property_name, type_name, | 132 def __init__(self, field_role, name_for_methods, property_name, type_name, |
| 102 field_template, size, default_value, **kwargs): | 133 field_template, field_group, size, default_value, **kwargs): |
| 103 """Creates a new field.""" | 134 """Creates a new field.""" |
| 104 self.name = class_member_name(name_for_methods) | 135 self.name = class_member_name(name_for_methods) |
| 105 self.property_name = property_name | 136 self.property_name = property_name |
| 106 self.type_name = type_name | 137 self.type_name = type_name |
| 107 self.field_template = field_template | 138 self.field_template = field_template |
| 139 self.field_group = field_group | |
| 108 self.size = size | 140 self.size = size |
| 109 self.default_value = default_value | 141 self.default_value = default_value |
| 110 | 142 |
| 111 # Field role: one of these must be true | 143 # Field role: one of these must be true |
| 112 self.is_property = field_role == 'property' | 144 self.is_property = field_role == 'property' |
| 113 self.is_inherited_flag = field_role == 'inherited_flag' | 145 self.is_inherited_flag = field_role == 'inherited_flag' |
| 114 self.is_nonproperty = field_role == 'nonproperty' | 146 self.is_nonproperty = field_role == 'nonproperty' |
| 115 assert (self.is_property, self.is_inherited_flag, self.is_nonproperty).c ount(True) == 1, \ | 147 assert (self.is_property, self.is_inherited_flag, self.is_nonproperty).c ount(True) == 1, \ |
| 116 'Field role has to be exactly one of: property, inherited_flag, nonp roperty' | 148 'Field role has to be exactly one of: property, inherited_flag, nonp roperty' |
| 117 | 149 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 139 """ | 171 """ |
| 140 Get a list of paths that need to be included for ComputedStyleBase. | 172 Get a list of paths that need to be included for ComputedStyleBase. |
| 141 """ | 173 """ |
| 142 include_paths = set() | 174 include_paths = set() |
| 143 for property_ in properties: | 175 for property_ in properties: |
| 144 if property_['field_type_path'] is not None: | 176 if property_['field_type_path'] is not None: |
| 145 include_paths.add(property_['field_type_path'] + '.h') | 177 include_paths.add(property_['field_type_path'] + '.h') |
| 146 return list(sorted(include_paths)) | 178 return list(sorted(include_paths)) |
| 147 | 179 |
| 148 | 180 |
| 181 def _group_fields(fields): | |
| 182 """Groups a list of fields by their field_group and returns the root group." "" | |
| 183 groups = defaultdict(list) | |
| 184 for field in fields: | |
| 185 groups[field.field_group].append(field) | |
| 186 | |
| 187 no_group = groups.pop(None) | |
| 188 subgroups = [Group(field_group, [], _reorder_fields(fields)) for field_group , fields in groups.items()] | |
| 189 return Group('', subgroups=subgroups, fields=_reorder_fields(no_group)) | |
| 190 | |
| 191 | |
| 149 def _create_enums(properties): | 192 def _create_enums(properties): |
| 150 """ | 193 """ |
| 151 Returns an OrderedDict of enums to be generated, enum name -> [list of enum values] | 194 Returns an OrderedDict of enums to be generated, enum name -> [list of enum values] |
| 152 """ | 195 """ |
| 153 enums = {} | 196 enums = {} |
| 154 for property_ in properties: | 197 for property_ in properties: |
| 155 # Only generate enums for keyword properties that use the default field_ type_path. | 198 # Only generate enums for keyword properties that use the default field_ type_path. |
| 156 if property_['field_template'] == 'keyword' and property_['field_type_pa th'] is None: | 199 if property_['field_template'] == 'keyword' and property_['field_type_pa th'] is None: |
| 157 enum_name = property_['type_name'] | 200 enum_name = property_['type_name'] |
| 158 enum_values = [enum_value_name(k) for k in property_['keywords']] | 201 enum_values = [enum_value_name(k) for k in property_['keywords']] |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 size = 1 | 245 size = 1 |
| 203 | 246 |
| 204 return Field( | 247 return Field( |
| 205 field_role, | 248 field_role, |
| 206 name_for_methods, | 249 name_for_methods, |
| 207 property_name=property_['name'], | 250 property_name=property_['name'], |
| 208 inherited=property_['inherited'], | 251 inherited=property_['inherited'], |
| 209 independent=property_['independent'], | 252 independent=property_['independent'], |
| 210 type_name=type_name, | 253 type_name=type_name, |
| 211 field_template=property_['field_template'], | 254 field_template=property_['field_template'], |
| 255 field_group=property_['field_group'], | |
| 212 size=size, | 256 size=size, |
| 213 default_value=default_value, | 257 default_value=default_value, |
| 214 ) | 258 ) |
| 215 | 259 |
| 216 | 260 |
| 217 def _create_inherited_flag_field(property_): | 261 def _create_inherited_flag_field(property_): |
| 218 """ | 262 """ |
| 219 Create the field used for an inheritance fast path from an independent CSS p roperty, | 263 Create the field used for an inheritance fast path from an independent CSS p roperty, |
| 220 and return the Field object. | 264 and return the Field object. |
| 221 """ | 265 """ |
| 222 return Field( | 266 return Field( |
| 223 'inherited_flag', | 267 'inherited_flag', |
| 224 join_name(property_['name_for_methods'], 'is inherited'), | 268 join_name(property_['name_for_methods'], 'is inherited'), |
| 225 property_name=property_['name'], | 269 property_name=property_['name'], |
| 226 type_name='bool', | 270 type_name='bool', |
| 227 field_template='flag', | 271 field_template='flag', |
| 272 field_group=property_['field_group'], | |
| 228 size=1, | 273 size=1, |
| 229 default_value='true', | 274 default_value='true', |
| 230 ) | 275 ) |
| 231 | 276 |
| 232 | 277 |
| 233 def _create_fields(field_role, properties): | 278 def _create_fields(field_role, properties): |
| 234 """ | 279 """ |
| 235 Create ComputedStyle fields from properties or nonproperties and return a li st of Field objects. | 280 Create ComputedStyle fields from properties or nonproperties and return a li st of Field objects. |
| 236 """ | 281 """ |
| 237 fields = [] | 282 fields = [] |
| 238 for property_ in properties: | 283 for property_ in properties: |
| 239 # Only generate properties that have a field template | 284 # Only generate properties that have a field template |
| 240 if property_['field_template'] is not None: | 285 if property_['field_template'] is not None: |
| 241 # If the property is independent, add the single-bit sized isInherit ed flag | 286 # If the property is independent, add the single-bit sized isInherit ed flag |
| 242 # to the list of Fields as well. | 287 # to the list of Fields as well. |
| 243 if property_['independent']: | 288 if property_['independent']: |
| 244 fields.append(_create_inherited_flag_field(property_)) | 289 fields.append(_create_inherited_flag_field(property_)) |
| 245 | 290 |
| 246 fields.append(_create_field(field_role, property_)) | 291 fields.append(_create_field(field_role, property_)) |
| 247 | 292 |
| 248 return fields | 293 return fields |
| 249 | 294 |
| 250 | 295 |
| 251 def _pack_fields(fields): | 296 def _reorder_fields(fields): |
|
meade_UTC10
2017/04/06 03:29:57
You're still doing packing though? I don't think t
shend
2017/04/06 04:39:39
For me, packing means the compiler "packing" the s
| |
| 252 """ | 297 """ |
| 253 Group a list of fields into buckets to minimise padding. | 298 Returns a list of fields ordered to minimise padding. |
| 254 Returns a list of buckets, where each bucket is a list of Field objects. | |
| 255 """ | 299 """ |
| 300 # Separate out bit fields from normal fields | |
| 301 bit_fields = [field for field in fields if field.is_bit_field] | |
| 302 normal_fields = [field for field in fields if not field.is_bit_field] | |
| 303 | |
| 256 # Since fields cannot cross word boundaries, in order to minimize | 304 # Since fields cannot cross word boundaries, in order to minimize |
| 257 # padding, group fields into buckets so that as many buckets as possible | 305 # padding, group fields into buckets so that as many buckets as possible |
| 258 # are exactly 32 bits. Although this greedy approach may not always | 306 # are exactly 32 bits. Although this greedy approach may not always |
| 259 # produce the optimal solution, we add a static_assert to the code to | 307 # produce the optimal solution, we add a static_assert to the code to |
| 260 # ensure ComputedStyleBase results in the expected size. If that | 308 # ensure ComputedStyleBase results in the expected size. If that |
| 261 # static_assert fails, this code is falling into the small number of | 309 # static_assert fails, this code is falling into the small number of |
| 262 # cases that are suboptimal, and may need to be rethought. | 310 # cases that are suboptimal, and may need to be rethought. |
| 263 # For more details on packing bit fields to reduce padding, see: | 311 # For more details on packing bit fields to reduce padding, see: |
| 264 # http://www.catb.org/esr/structure-packing/#_bitfields | 312 # http://www.catb.org/esr/structure-packing/#_bitfields |
| 265 field_buckets = [] | 313 field_buckets = [] |
| 266 # Consider fields in descending order of size to reduce fragmentation | 314 # Consider fields in descending order of size to reduce fragmentation |
| 267 # when they are selected. Ties broken in alphabetical order by name. | 315 # when they are selected. Ties broken in alphabetical order by name. |
| 268 for field in sorted(fields, key=lambda f: (-f.size, f.name)): | 316 for field in sorted(bit_fields, key=lambda f: (-f.size, f.name)): |
| 269 added_to_bucket = False | 317 added_to_bucket = False |
| 270 # Go through each bucket and add this field if it will not increase | 318 # Go through each bucket and add this field if it will not increase |
| 271 # the bucket's size to larger than 32 bits. Otherwise, make a new | 319 # the bucket's size to larger than 32 bits. Otherwise, make a new |
| 272 # bucket containing only this field. | 320 # bucket containing only this field. |
| 273 for bucket in field_buckets: | 321 for bucket in field_buckets: |
| 274 if sum(f.size for f in bucket) + field.size <= 32: | 322 if sum(f.size for f in bucket) + field.size <= 32: |
| 275 bucket.append(field) | 323 bucket.append(field) |
| 276 added_to_bucket = True | 324 added_to_bucket = True |
| 277 break | 325 break |
| 278 if not added_to_bucket: | 326 if not added_to_bucket: |
| 279 field_buckets.append([field]) | 327 field_buckets.append([field]) |
| 280 | 328 |
| 281 return field_buckets | 329 # Normal fields go first, then the bit fields. |
| 330 return list(normal_fields) + _flatten_list(field_buckets) | |
| 282 | 331 |
| 283 | 332 |
| 284 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): | 333 class ComputedStyleBaseWriter(make_style_builder.StyleBuilderWriter): |
| 285 def __init__(self, json5_file_path): | 334 def __init__(self, json5_file_path): |
| 286 super(ComputedStyleBaseWriter, self).__init__(json5_file_path) | 335 super(ComputedStyleBaseWriter, self).__init__(json5_file_path) |
| 287 self._outputs = { | 336 self._outputs = { |
| 288 'ComputedStyleBase.h': self.generate_base_computed_style_h, | 337 'ComputedStyleBase.h': self.generate_base_computed_style_h, |
| 289 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp, | 338 'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp, |
| 290 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co nstants, | 339 'ComputedStyleBaseConstants.h': self.generate_base_computed_style_co nstants, |
| 291 'CSSValueIDMappingsGenerated.h': self.generate_css_value_mappings, | 340 'CSSValueIDMappingsGenerated.h': self.generate_css_value_mappings, |
| 292 } | 341 } |
| 293 | 342 |
| 294 # TODO(shend): Remove this once we move NONPROPERTIES to its own JSON fi le, | 343 # TODO(shend): Remove this once we move NONPROPERTIES to its own JSON fi le, |
| 295 # since the JSON5 reader will handle missing fields and defaults. | 344 # since the JSON5 reader will handle missing fields and defaults. |
| 296 for property_ in NONPROPERTIES: | 345 for property_ in NONPROPERTIES: |
| 297 property_['name_for_methods'] = property_['name'] | 346 property_['name_for_methods'] = property_['name'] |
| 298 if 'field_type_path' not in property_: | 347 if 'field_type_path' not in property_: |
| 299 property_['field_type_path'] = None | 348 property_['field_type_path'] = None |
| 300 if 'type_name' not in property_: | 349 if 'type_name' not in property_: |
| 301 property_['type_name'] = 'E' + enum_type_name(property_['name_fo r_methods']) | 350 property_['type_name'] = 'E' + enum_type_name(property_['name_fo r_methods']) |
| 351 if 'field_group' not in property_: | |
| 352 property_['field_group'] = None | |
| 302 | 353 |
| 303 property_values = self._properties.values() | 354 property_values = self._properties.values() |
| 304 | 355 |
| 305 # Override the type name when field_type_path is specified | 356 # Override the type name when field_type_path is specified |
| 306 for property_ in property_values: | 357 for property_ in property_values: |
| 307 if property_['field_type_path']: | 358 if property_['field_type_path']: |
| 308 property_['type_name'] = property_['field_type_path'].split('/') [-1] | 359 property_['type_name'] = property_['field_type_path'].split('/') [-1] |
| 309 | 360 |
| 310 self._generated_enums = _create_enums(property_values + NONPROPERTIES) | 361 self._generated_enums = _create_enums(property_values + NONPROPERTIES) |
| 311 | 362 |
| 312 all_fields = (_create_fields('property', property_values) + | 363 fields = (_create_fields('property', property_values) + |
| 313 _create_fields('nonproperty', NONPROPERTIES)) | 364 _create_fields('nonproperty', NONPROPERTIES)) |
| 314 | 365 |
| 315 # Separate the normal fields from the bit fields | 366 # Separate fields into groups |
| 316 bit_fields = [field for field in all_fields if field.is_bit_field] | 367 self._base_group = _group_fields(fields) |
| 317 normal_fields = [field for field in all_fields if not field.is_bit_field ] | |
| 318 | 368 |
| 319 # Pack bit fields into buckets | 369 # Get include paths |
|
meade_UTC10
2017/04/06 03:29:57
Is this really a helpful comment? :p
shend
2017/04/06 04:39:40
lol, removed.
| |
| 320 field_buckets = _pack_fields(bit_fields) | 370 self._include_paths = _get_include_paths(property_values) |
| 321 | |
| 322 # The expected size of ComputedStyleBase is equivalent to as many words | |
| 323 # as the total number of buckets. | |
| 324 self._expected_bit_field_bytes = len(field_buckets) | |
| 325 | |
| 326 # The most optimal size of ComputedStyleBase is the total sum of all the | |
| 327 # field sizes, rounded up to the nearest word. If this produces the | |
| 328 # incorrect value, either the packing algorithm is not optimal or there | |
| 329 # is no way to pack the fields such that excess padding space is not | |
| 330 # added. | |
| 331 # If this fails, increase extra_padding_bytes by 1, but be aware that | |
| 332 # this also increases ComputedStyleBase by 1 word. | |
| 333 # We should be able to bring extra_padding_bytes back to 0 from time to | |
| 334 # time. | |
| 335 extra_padding_bytes = 0 | |
| 336 optimal_bit_field_bytes = int(math.ceil(sum(f.size for f in bit_fields) / 32.0)) | |
| 337 real_bit_field_bytes = optimal_bit_field_bytes + extra_padding_bytes | |
| 338 assert self._expected_bit_field_bytes == real_bit_field_bytes, \ | |
| 339 ('The field packing algorithm produced %s bytes, optimal is %s bytes ' % | |
| 340 (self._expected_bit_field_bytes, real_bit_field_bytes)) | |
| 341 | |
| 342 # Normal fields go first, then the bit fields. | |
| 343 self._fields = list(normal_fields) | |
| 344 | |
| 345 # Order the fields so fields in each bucket are adjacent. | |
| 346 for bucket in field_buckets: | |
| 347 for field in bucket: | |
| 348 self._fields.append(field) | |
| 349 | |
| 350 self._include_paths = _get_include_paths(property_values + NONPROPERTIES ) | |
| 351 | |
| 352 | 371 |
| 353 @template_expander.use_jinja('ComputedStyleBase.h.tmpl') | 372 @template_expander.use_jinja('ComputedStyleBase.h.tmpl') |
| 354 def generate_base_computed_style_h(self): | 373 def generate_base_computed_style_h(self): |
| 355 return { | 374 return { |
| 356 'properties': self._properties, | 375 'properties': self._properties, |
| 357 'enums': self._generated_enums, | 376 'enums': self._generated_enums, |
| 358 'include_paths': self._include_paths, | 377 'include_paths': self._include_paths, |
| 359 'fields': self._fields, | 378 'computed_style': self._base_group, |
| 360 } | 379 } |
| 361 | 380 |
| 362 @template_expander.use_jinja('ComputedStyleBase.cpp.tmpl') | 381 @template_expander.use_jinja('ComputedStyleBase.cpp.tmpl') |
| 363 def generate_base_computed_style_cpp(self): | 382 def generate_base_computed_style_cpp(self): |
| 364 return { | 383 return { |
| 365 'properties': self._properties, | 384 'properties': self._properties, |
| 366 'enums': self._generated_enums, | 385 'enums': self._generated_enums, |
| 367 'fields': self._fields, | 386 'computed_style': self._base_group, |
| 368 'expected_bit_field_bytes': self._expected_bit_field_bytes, | |
| 369 } | 387 } |
| 370 | 388 |
| 371 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 389 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
| 372 def generate_base_computed_style_constants(self): | 390 def generate_base_computed_style_constants(self): |
| 373 return { | 391 return { |
| 374 'properties': self._properties, | 392 'properties': self._properties, |
| 375 'enums': self._generated_enums, | 393 'enums': self._generated_enums, |
| 376 'fields': self._fields, | |
| 377 } | 394 } |
| 378 | 395 |
| 379 @template_expander.use_jinja('CSSValueIDMappingsGenerated.h.tmpl') | 396 @template_expander.use_jinja('CSSValueIDMappingsGenerated.h.tmpl') |
| 380 def generate_css_value_mappings(self): | 397 def generate_css_value_mappings(self): |
| 381 mappings = {} | 398 mappings = {} |
| 382 | 399 |
| 383 for property_ in self._properties.values(): | 400 for property_ in self._properties.values(): |
| 384 if property_['field_template'] == 'keyword': | 401 if property_['field_template'] == 'keyword': |
| 385 mappings[property_['type_name']] = { | 402 mappings[property_['type_name']] = { |
| 386 'default_value': enum_value_name(property_['default_value']) , | 403 'default_value': enum_value_name(property_['default_value']) , |
| 387 'mapping': [(enum_value_name(k), enum_for_css_keyword(k)) fo r k in property_['keywords']], | 404 'mapping': [(enum_value_name(k), enum_for_css_keyword(k)) fo r k in property_['keywords']], |
| 388 } | 405 } |
| 389 | 406 |
| 390 return { | 407 return { |
| 391 'include_paths': self._include_paths, | 408 'include_paths': self._include_paths, |
| 392 'mappings': mappings, | 409 'mappings': mappings, |
| 393 } | 410 } |
| 394 | 411 |
| 395 if __name__ == '__main__': | 412 if __name__ == '__main__': |
| 396 json5_generator.Maker(ComputedStyleBaseWriter).main() | 413 json5_generator.Maker(ComputedStyleBaseWriter).main() |
| OLD | NEW |