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 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 Almost all properties will have at least one Field, often more than one. | 69 Almost all properties will have at least one Field, often more than one. |
70 | 70 |
71 Most attributes in this class correspond to parameters in CSSProperties.json
5. | 71 Most attributes in this class correspond to parameters in CSSProperties.json
5. |
72 See that file for a more detailed explanation of each attribute. | 72 See that file for a more detailed explanation of each attribute. |
73 | 73 |
74 Attributes: | 74 Attributes: |
75 field_role: The semantic role of the field. Can be: | 75 field_role: The semantic role of the field. Can be: |
76 - 'property': for fields that store CSS properties | 76 - 'property': for fields that store CSS properties |
77 - 'inherited_flag': for single-bit flags that store whether a proper
ty is | 77 - 'inherited_flag': for single-bit flags that store whether a proper
ty is |
78 inherited by this style or set explicitly | 78 inherited by this style or set explicitly |
79 - 'nonproperty': for fields that are not CSS properties | |
80 name_for_methods: String used to form the names of getters and setters. | 79 name_for_methods: String used to form the names of getters and setters. |
81 Should be in upper camel case. | 80 Should be in upper camel case. |
82 property_name: Name of the property that the field is part of. | 81 property_name: Name of the property that the field is part of. |
83 type_name: Name of the C++ type exposed by the generated interface (e.g.
EClear, int). | 82 type_name: Name of the C++ type exposed by the generated interface (e.g.
EClear, int). |
84 field_template: Determines the interface generated for the field. Can be
one of: | 83 field_template: Determines the interface generated for the field. Can be
one of: |
85 keyword, flag, or monotonic_flag. | 84 keyword, flag, or monotonic_flag. |
86 field_group: The name of the group that this field is inside. | 85 field_group: The name of the group that this field is inside. |
87 size: Number of bits needed for storage. | 86 size: Number of bits needed for storage. |
88 default_value: Default value for this field when it is first initialized
. | 87 default_value: Default value for this field when it is first initialized
. |
89 """ | 88 """ |
90 | 89 |
91 def __init__(self, field_role, name_for_methods, property_name, type_name, | 90 def __init__(self, field_role, name_for_methods, property_name, type_name, |
92 field_template, field_group, size, default_value, | 91 field_template, field_group, size, default_value, has_custom_co
mpare_and_copy, |
93 getter_method_name, setter_method_name, initial_method_name, **
kwargs): | 92 getter_method_name, setter_method_name, initial_method_name, **
kwargs): |
94 """Creates a new field.""" | 93 """Creates a new field.""" |
95 self.name = class_member_name(name_for_methods) | 94 self.name = class_member_name(name_for_methods) |
96 self.property_name = property_name | 95 self.property_name = property_name |
97 self.type_name = type_name | 96 self.type_name = type_name |
98 self.field_template = field_template | 97 self.field_template = field_template |
99 self.group_name = field_group | 98 self.group_name = field_group |
100 self.group_member_name = class_member_name(join_name(field_group, 'data'
)) if field_group else None | 99 self.group_member_name = class_member_name(join_name(field_group, 'data'
)) if field_group else None |
101 self.size = size | 100 self.size = size |
102 self.default_value = default_value | 101 self.default_value = default_value |
| 102 self.has_custom_compare_and_copy = has_custom_compare_and_copy |
103 | 103 |
104 # Field role: one of these must be true | 104 # Field role: one of these must be true |
105 self.is_property = field_role == 'property' | 105 self.is_property = field_role == 'property' |
106 self.is_inherited_flag = field_role == 'inherited_flag' | 106 self.is_inherited_flag = field_role == 'inherited_flag' |
107 self.is_nonproperty = field_role == 'nonproperty' | 107 assert (self.is_property, self.is_inherited_flag).count(True) == 1, \ |
108 assert (self.is_property, self.is_inherited_flag, self.is_nonproperty).c
ount(True) == 1, \ | 108 'Field role has to be exactly one of: property, inherited_flag' |
109 'Field role has to be exactly one of: property, inherited_flag, nonp
roperty' | |
110 | 109 |
111 if not self.is_inherited_flag: | 110 if not self.is_inherited_flag: |
112 self.is_inherited = kwargs.pop('inherited') | 111 self.is_inherited = kwargs.pop('inherited') |
113 self.is_independent = kwargs.pop('independent') | 112 self.is_independent = kwargs.pop('independent') |
114 assert self.is_inherited or not self.is_independent, 'Only inherited
fields can be independent' | 113 assert self.is_inherited or not self.is_independent, 'Only inherited
fields can be independent' |
115 | 114 |
116 self.is_inherited_method_name = method_name(join_name(name_for_metho
ds, 'is inherited')) | 115 self.is_inherited_method_name = method_name(join_name(name_for_metho
ds, 'is inherited')) |
117 | 116 |
118 # Method names | 117 # Method names |
119 # TODO(nainar): Method name generation is inconsistent. Fix. | 118 # TODO(nainar): Method name generation is inconsistent. Fix. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 ("'" + property_['name'] + "' can't have type_name '" + enum
_name + "' " | 169 ("'" + property_['name'] + "' can't have type_name '" + enum
_name + "' " |
171 "because it was used by a previous property, but with a dif
ferent set of keywords. " | 170 "because it was used by a previous property, but with a dif
ferent set of keywords. " |
172 "Either give it a different name or ensure the keywords are
the same.") | 171 "Either give it a different name or ensure the keywords are
the same.") |
173 | 172 |
174 enums[enum_name] = enum_values | 173 enums[enum_name] = enum_values |
175 | 174 |
176 # Return the enums sorted by key (enum name) | 175 # Return the enums sorted by key (enum name) |
177 return OrderedDict(sorted(enums.items(), key=lambda t: t[0])) | 176 return OrderedDict(sorted(enums.items(), key=lambda t: t[0])) |
178 | 177 |
179 | 178 |
180 def _create_field(field_role, property_): | 179 def _create_property_field(property_): |
181 """ | 180 """ |
182 Create a property or nonproperty field. | 181 Create a property field. |
183 """ | 182 """ |
184 assert field_role in ('property', 'nonproperty') | |
185 | |
186 name_for_methods = property_['name_for_methods'] | 183 name_for_methods = property_['name_for_methods'] |
187 | 184 |
188 assert property_['default_value'] is not None, \ | 185 assert property_['default_value'] is not None, \ |
189 ('MakeComputedStyleBase requires an default value for all fields, none s
pecified ' | 186 ('MakeComputedStyleBase requires an default value for all fields, none s
pecified ' |
190 'for property ' + property_['name']) | 187 'for property ' + property_['name']) |
191 | 188 |
192 if property_['field_template'] == 'keyword': | 189 if property_['field_template'] == 'keyword': |
193 type_name = property_['type_name'] | 190 type_name = property_['type_name'] |
194 default_value = type_name + '::' + enum_value_name(property_['default_va
lue']) | 191 default_value = type_name + '::' + enum_value_name(property_['default_va
lue']) |
195 size = int(math.ceil(math.log(len(property_['keywords']), 2))) | 192 size = int(math.ceil(math.log(len(property_['keywords']), 2))) |
(...skipping 10 matching lines...) Expand all Loading... |
206 type_name = property_['type_name'] | 203 type_name = property_['type_name'] |
207 default_value = property_['default_value'] | 204 default_value = property_['default_value'] |
208 size = 1 if type_name == 'bool' else None # pack bools with 1 bit. | 205 size = 1 if type_name == 'bool' else None # pack bools with 1 bit. |
209 else: | 206 else: |
210 assert property_['field_template'] in ('monotonic_flag',) | 207 assert property_['field_template'] in ('monotonic_flag',) |
211 type_name = 'bool' | 208 type_name = 'bool' |
212 default_value = 'false' | 209 default_value = 'false' |
213 size = 1 | 210 size = 1 |
214 | 211 |
215 return Field( | 212 return Field( |
216 field_role, | 213 'property', |
217 name_for_methods, | 214 name_for_methods, |
218 property_name=property_['name'], | 215 property_name=property_['name'], |
219 inherited=property_['inherited'], | 216 inherited=property_['inherited'], |
220 independent=property_['independent'], | 217 independent=property_['independent'], |
221 type_name=type_name, | 218 type_name=type_name, |
222 field_template=property_['field_template'], | 219 field_template=property_['field_template'], |
223 field_group=property_['field_group'], | 220 field_group=property_['field_group'], |
224 size=size, | 221 size=size, |
225 default_value=default_value, | 222 default_value=default_value, |
| 223 has_custom_compare_and_copy=property_['has_custom_compare_and_copy'], |
226 getter_method_name=property_['getter'], | 224 getter_method_name=property_['getter'], |
227 setter_method_name=property_['setter'], | 225 setter_method_name=property_['setter'], |
228 initial_method_name=property_['initial'], | 226 initial_method_name=property_['initial'], |
229 ) | 227 ) |
230 | 228 |
231 | 229 |
232 def _create_inherited_flag_field(property_): | 230 def _create_inherited_flag_field(property_): |
233 """ | 231 """ |
234 Create the field used for an inheritance fast path from an independent CSS p
roperty, | 232 Create the field used for an inheritance fast path from an independent CSS p
roperty, |
235 and return the Field object. | 233 and return the Field object. |
236 """ | 234 """ |
237 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') | 235 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') |
238 return Field( | 236 return Field( |
239 'inherited_flag', | 237 'inherited_flag', |
240 name_for_methods, | 238 name_for_methods, |
241 property_name=property_['name'], | 239 property_name=property_['name'], |
242 type_name='bool', | 240 type_name='bool', |
243 field_template='primitive', | 241 field_template='primitive', |
244 field_group=property_['field_group'], | 242 field_group=property_['field_group'], |
245 size=1, | 243 size=1, |
246 default_value='true', | 244 default_value='true', |
| 245 has_custom_compare_and_copy=False, |
247 getter_method_name=method_name(name_for_methods), | 246 getter_method_name=method_name(name_for_methods), |
248 setter_method_name=method_name(join_name('set', name_for_methods)), | 247 setter_method_name=method_name(join_name('set', name_for_methods)), |
249 initial_method_name=method_name(join_name('initial', name_for_methods)), | 248 initial_method_name=method_name(join_name('initial', name_for_methods)), |
250 ) | 249 ) |
251 | 250 |
252 | 251 |
253 def _create_fields(properties): | 252 def _create_fields(properties): |
254 """ | 253 """ |
255 Create ComputedStyle fields from properties or nonproperties and return a li
st of Field objects. | 254 Create ComputedStyle fields from properties and return a list of Field objec
ts. |
256 """ | 255 """ |
257 fields = [] | 256 fields = [] |
258 for property_ in properties: | 257 for property_ in properties: |
259 # Only generate properties that have a field template | 258 # Only generate properties that have a field template |
260 if property_['field_template'] is not None: | 259 if property_['field_template'] is not None: |
261 # If the property is independent, add the single-bit sized isInherit
ed flag | 260 # If the property is independent, add the single-bit sized isInherit
ed flag |
262 # to the list of Fields as well. | 261 # to the list of Fields as well. |
263 if property_['independent']: | 262 if property_['independent']: |
264 fields.append(_create_inherited_flag_field(property_)) | 263 fields.append(_create_inherited_flag_field(property_)) |
265 | 264 |
266 # TODO(shend): Get rid of the property/nonproperty field roles. | 265 fields.append(_create_property_field(property_)) |
267 # If the field has_custom_compare_and_copy, then it does not appear
in | |
268 # ComputedStyle::operator== and ComputedStyle::CopyNonInheritedFromC
ached. | |
269 field_role = 'nonproperty' if property_['has_custom_compare_and_copy
'] else 'property' | |
270 fields.append(_create_field(field_role, property_)) | |
271 | 266 |
272 return fields | 267 return fields |
273 | 268 |
274 | 269 |
275 def _reorder_fields(fields): | 270 def _reorder_fields(fields): |
276 """ | 271 """ |
277 Returns a list of fields ordered to minimise padding. | 272 Returns a list of fields ordered to minimise padding. |
278 """ | 273 """ |
279 # Separate out bit fields from non bit fields | 274 # Separate out bit fields from non bit fields |
280 bit_fields = [field for field in fields if field.is_bit_field] | 275 bit_fields = [field for field in fields if field.is_bit_field] |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 | 373 |
379 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 374 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
380 def generate_base_computed_style_constants(self): | 375 def generate_base_computed_style_constants(self): |
381 return { | 376 return { |
382 'properties': self._properties, | 377 'properties': self._properties, |
383 'enums': self._generated_enums, | 378 'enums': self._generated_enums, |
384 } | 379 } |
385 | 380 |
386 if __name__ == '__main__': | 381 if __name__ == '__main__': |
387 json5_generator.Maker(ComputedStyleBaseWriter).main() | 382 json5_generator.Maker(ComputedStyleBaseWriter).main() |
OLD | NEW |