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

Side by Side Diff: build/android/gyp/generate_v14_compatible_resources.py

Issue 14812015: [Android] Auto-generate only necessary v14 resources. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: (newt's comment) added 'compatible' on comment Created 7 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « build/android/gyp/copy_v17_resources.py ('k') | build/android/gyp/generate_v14_resources.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright 2013 The Chromium Authors. All rights reserved. 3 # Copyright 2013 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Convert Android xml resources to API 14 compatible. 7 """Convert Android xml resources to API 14 compatible.
8 8
9 There are two reasons that we cannot just use API attributes, 9 There are two reasons that we cannot just use API 17 attributes,
10 so we are generating another set of resources by this script. 10 so we are generating another set of resources by this script.
11 11
12 1. paddingStart attribute can cause a crash on Galaxy Tab 2. 12 1. paddingStart attribute can cause a crash on Galaxy Tab 2.
13 2. There is a bug that paddingStart does not override paddingLeft on 13 2. There is a bug that paddingStart does not override paddingLeft on
14 JB-MR1. This is fixed on JB-MR2. 14 JB-MR1. This is fixed on JB-MR2.
15 15
16 Therefore, this resource generation script can be removed when 16 Therefore, this resource generation script can be removed when
17 we drop the support for JB-MR1. 17 we drop the support for JB-MR1.
18 18
19 Please refer to http://crbug.com/235118 for the details. 19 Please refer to http://crbug.com/235118 for the details.
20 """ 20 """
21 21
22 import optparse 22 import optparse
23 import os 23 import os
24 import re 24 import shutil
25 import sys 25 import sys
26 import xml.dom.minidom as minidom 26 import xml.dom.minidom as minidom
27 27
28 from util import build_utils 28 from util import build_utils
29 29
30 # Note that we are assuming 'android:' is an alias of 30 # Note that we are assuming 'android:' is an alias of
31 # the namespace 'http://schemas.android.com/apk/res/android'. 31 # the namespace 'http://schemas.android.com/apk/res/android'.
32 32
33 GRAVITY_ATTRIBUTES = ('android:gravity', 'android:layout_gravity') 33 GRAVITY_ATTRIBUTES = ('android:gravity', 'android:layout_gravity')
34 34
(...skipping 22 matching lines...) Expand all
57 def IterateXmlElements(node): 57 def IterateXmlElements(node):
58 """minidom helper function that iterates all the element nodes. 58 """minidom helper function that iterates all the element nodes.
59 Iteration order is pre-order depth-first.""" 59 Iteration order is pre-order depth-first."""
60 if node.nodeType == node.ELEMENT_NODE: 60 if node.nodeType == node.ELEMENT_NODE:
61 yield node 61 yield node
62 for child_node in node.childNodes: 62 for child_node in node.childNodes:
63 for child_node_element in IterateXmlElements(child_node): 63 for child_node_element in IterateXmlElements(child_node):
64 yield child_node_element 64 yield child_node_element
65 65
66 66
67 def WarnDeprecatedAttribute(name, value, filename): 67 def WarnIfDeprecatedAttribute(name, value, filename):
68 """print a warning message if the given attribute is deprecated."""
68 if name in ATTRIBUTES_TO_MAP_REVERSED: 69 if name in ATTRIBUTES_TO_MAP_REVERSED:
69 print >> sys.stderr, ('warning: ' + filename + ' should use ' + 70 print >> sys.stderr, ('warning: ' + filename + ' should use ' +
70 ATTRIBUTES_TO_MAP_REVERSED[name] + 71 ATTRIBUTES_TO_MAP_REVERSED[name] +
71 ' instead of ' + name) 72 ' instead of ' + name)
72 elif name in GRAVITY_ATTRIBUTES and ('left' in value or 'right' in value): 73 elif name in GRAVITY_ATTRIBUTES and ('left' in value or 'right' in value):
73 print >> sys.stderr, ('warning: ' + filename + 74 print >> sys.stderr, ('warning: ' + filename +
74 ' should use start/end instead of left/right for ' + 75 ' should use start/end instead of left/right for ' +
75 name) 76 name)
76 77
77 78
78 def GenerateV14StyleResource(input_filename, output_filename): 79 def GenerateV14LayoutResource(dom, filename):
79 """Convert style resource to API 14 compatible style resource.
80
81 It's mostly a simple replacement, s/Start/Left s/End/Right,
82 on the attribute names specified by <item> element.
83 If input_filename does not contain style resources, do nothing.
84 """
85 dom = minidom.parse(input_filename)
86 style_elements = dom.getElementsByTagName('style')
87
88 if not style_elements:
89 return
90
91 for style_element in style_elements:
92 for item_element in style_element.getElementsByTagName('item'):
93 name = item_element.attributes['name'].value
94 value = item_element.childNodes[0].nodeValue
95 if name in ATTRIBUTES_TO_MAP:
96 item_element.attributes['name'].value = ATTRIBUTES_TO_MAP[name]
97 else:
98 WarnDeprecatedAttribute(name, value, input_filename)
99
100 build_utils.MakeDirectory(os.path.dirname(output_filename))
101 with open(output_filename, 'w') as f:
102 dom.writexml(f, '', ' ', '\n', encoding='utf-8')
103
104
105 def GenerateV14LayoutResource(input_filename, output_filename):
106 """Convert layout resource to API 14 compatible layout resource. 80 """Convert layout resource to API 14 compatible layout resource.
107 81
108 It's mostly a simple replacement, s/Start/Left s/End/Right, 82 Args:
109 on the attribute names. 83 dom: parsed minidom object to be modified.
84 filename: file name to display in case we print warnings.
85 Returns:
86 True if dom is modified, False otherwise.
110 """ 87 """
111 dom = minidom.parse(input_filename) 88 is_modified = False
112 89
113 # Iterate all the elements' attributes to find attributes to convert. 90 # Iterate all the elements' attributes to find attributes to convert.
114 for element in IterateXmlElements(dom): 91 for element in IterateXmlElements(dom):
115 for name, value in list(element.attributes.items()): 92 for name, value in list(element.attributes.items()):
116 # Convert any other API 17 Start/End attributes to Left/Right attributes. 93 # Convert any API 17 Start/End attributes to Left/Right attributes.
117 # For example, from paddingStart="10dp" to paddingLeft="10dp" 94 # For example, from paddingStart="10dp" to paddingLeft="10dp"
118 # Note: gravity attributes are not necessary to convert because 95 # Note: gravity attributes are not necessary to convert because
119 # start/end values are backward-compatible. Explained at 96 # start/end values are backward-compatible. Explained at
120 # https://plus.sandbox.google.com/+RomanNurik/posts/huuJd8iVVXY?e=Showroom 97 # https://plus.sandbox.google.com/+RomanNurik/posts/huuJd8iVVXY?e=Showroom
121 if name in ATTRIBUTES_TO_MAP: 98 if name in ATTRIBUTES_TO_MAP:
122 element.setAttribute(ATTRIBUTES_TO_MAP[name], value) 99 element.setAttribute(ATTRIBUTES_TO_MAP[name], value)
123 del element.attributes[name] 100 del element.attributes[name]
101 is_modified = True
124 else: 102 else:
125 WarnDeprecatedAttribute(name, value, input_filename) 103 WarnIfDeprecatedAttribute(name, value, filename)
126 104
127 build_utils.MakeDirectory(os.path.dirname(output_filename)) 105 return is_modified
128 with open(output_filename, 'w') as f:
129 dom.writexml(f, '', ' ', '\n', encoding='utf-8')
130 106
131 107
132 def GenerateV14XmlResourcesInDir(input_dir, output_dir, only_styles=False): 108 def GenerateV14StyleResource(dom, filename):
109 """Convert style resource to API 14 compatible style resource.
110
111 Args:
112 dom: parsed minidom object to be modified.
113 filename: file name to display in case we print warnings.
114 Returns:
115 True if dom is modified, False otherwise.
116 """
117 is_modified = False
118
119 for style_element in dom.getElementsByTagName('style'):
120 for item_element in style_element.getElementsByTagName('item'):
121 name = item_element.attributes['name'].value
122 value = item_element.childNodes[0].nodeValue
123 if name in ATTRIBUTES_TO_MAP:
124 item_element.attributes['name'].value = ATTRIBUTES_TO_MAP[name]
125 is_modified = True
126 else:
127 WarnIfDeprecatedAttribute(name, value, filename)
128
129 return is_modified
130
131
132 def GenerateV14Resource(input_filename,
133 output_v14_filename,
134 output_v17_filename):
135 """Convert layout/style resource to API 14 compatible layout/style resource.
136
137 It's mostly a simple replacement, s/Start/Left s/End/Right,
138 on the attribute names.
139 If the generated resource is identical to the original resource,
140 don't do anything. If not, write the generated resource to
141 output_v14_filename, and copy the original resource to output_v17_filename.
142 """
143 dom = minidom.parse(input_filename)
144
145 root_node = IterateXmlElements(dom).next()
146 if root_node.nodeName == 'resources':
147 # Style resources are under 'values*/' directory.
148 is_modified = GenerateV14StyleResource(dom, input_filename)
149 else:
150 # Layout resources can be under 'layout*/' or 'xml*/' directory.
151 is_modified = GenerateV14LayoutResource(dom, input_filename)
152
153 if is_modified:
154 # Write the generated resource.
155 build_utils.MakeDirectory(os.path.dirname(output_v14_filename))
156 with open(output_v14_filename, 'w') as f:
157 dom.writexml(f, '', ' ', '\n', encoding='utf-8')
158
159 # Copy the original resource.
160 build_utils.MakeDirectory(os.path.dirname(output_v17_filename))
161 shutil.copy2(input_filename, output_v17_filename)
162
163
164 def GenerateV14XmlResourcesInDir(input_dir, output_v14_dir, output_v17_dir):
133 """Convert resources to API 14 compatible XML resources in the directory.""" 165 """Convert resources to API 14 compatible XML resources in the directory."""
134 for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'): 166 for input_filename in build_utils.FindInDirectory(input_dir, '*.xml'):
135 output_filename = os.path.join(output_dir, 167 rel_filename = os.path.relpath(input_filename, input_dir)
136 os.path.relpath(input_filename, input_dir)) 168 output_v14_filename = os.path.join(output_v14_dir, rel_filename)
137 if only_styles: 169 output_v17_filename = os.path.join(output_v17_dir, rel_filename)
138 GenerateV14StyleResource(input_filename, output_filename) 170 GenerateV14Resource(input_filename, output_v14_filename,
139 else: 171 output_v17_filename)
140 GenerateV14LayoutResource(input_filename, output_filename)
141 172
142 173
143 def ParseArgs(): 174 def ParseArgs():
144 """Parses command line options. 175 """Parses command line options.
145 176
146 Returns: 177 Returns:
147 An options object as from optparse.OptionsParser.parse_args() 178 An options object as from optparse.OptionsParser.parse_args()
148 """ 179 """
149 parser = optparse.OptionParser() 180 parser = optparse.OptionParser()
150 parser.add_option('--res-dir', 181 parser.add_option('--res-dir',
151 help='directory containing resources ' 182 help='directory containing resources '
152 'used to generate v14 resources') 183 'used to generate v14 compatible resources')
153 parser.add_option('--res-v14-dir', 184 parser.add_option('--res-v14-compatibility-dir',
154 help='output directory into which ' 185 help='output directory into which '
155 'v14 resources will be generated') 186 'v14 compatible resources will be generated')
156 parser.add_option('--stamp', help='File to touch on success') 187 parser.add_option('--stamp', help='File to touch on success')
157 188
158 options, args = parser.parse_args() 189 options, args = parser.parse_args()
159 190
160 if args: 191 if args:
161 parser.error('No positional arguments should be given.') 192 parser.error('No positional arguments should be given.')
162 193
163 # Check that required options have been provided. 194 # Check that required options have been provided.
164 required_options = ('res_dir', 'res_v14_dir') 195 required_options = ('res_dir', 'res_v14_compatibility_dir')
165 build_utils.CheckOptions(options, parser, required=required_options) 196 build_utils.CheckOptions(options, parser, required=required_options)
166 return options 197 return options
167 198
168 199
169 def main(argv): 200 def main(argv):
170 options = ParseArgs() 201 options = ParseArgs()
171 202
172 build_utils.DeleteDirectory(options.res_v14_dir) 203 build_utils.DeleteDirectory(options.res_v14_compatibility_dir)
173 build_utils.MakeDirectory(options.res_v14_dir) 204 build_utils.MakeDirectory(options.res_v14_compatibility_dir)
174 205
175 for name in os.listdir(options.res_dir): 206 for name in os.listdir(options.res_dir):
176 if not os.path.isdir(os.path.join(options.res_dir, name)): 207 if not os.path.isdir(os.path.join(options.res_dir, name)):
177 continue 208 continue
178 209
179 dir_pieces = name.split('-') 210 dir_pieces = name.split('-')
180 resource_type = dir_pieces[0] 211 resource_type = dir_pieces[0]
181 qualifiers = dir_pieces[1:] 212 qualifiers = dir_pieces[1:]
182 213
183 # Android pre-v17 API doesn't support RTL. Skip. 214 # Android pre-v17 API doesn't support RTL. Skip.
184 if 'ldrtl' in qualifiers: 215 if 'ldrtl' in qualifiers:
185 continue 216 continue
186 217
218 # We also need to copy the original v17 resource to *-v17 directory
219 # because the generated v14 resource will hide the original resource.
187 input_dir = os.path.join(options.res_dir, name) 220 input_dir = os.path.join(options.res_dir, name)
188 output_dir = os.path.join(options.res_v14_dir, name) 221 output_v14_dir = os.path.join(options.res_v14_compatibility_dir, name)
222 output_v17_dir = os.path.join(options.res_v14_compatibility_dir, name +
223 '-v17')
189 224
190 # We only convert resources under layout*/, xml*/, 225 # We only convert resources under layout*/, xml*/,
191 # and style resources under values*/. 226 # and style resources under values*/.
192 # TODO(kkimlabs): don't process xml directly once all layouts have 227 # TODO(kkimlabs): don't process xml directly once all layouts have
193 # been moved out of XML directory. see http://crbug.com/238458 228 # been moved out of XML directory. see http://crbug.com/238458
194 if resource_type in ('layout', 'xml'): 229 if resource_type in ('layout', 'xml', 'values'):
195 GenerateV14XmlResourcesInDir(input_dir, output_dir) 230 GenerateV14XmlResourcesInDir(input_dir, output_v14_dir, output_v17_dir)
196 elif resource_type in ('values'):
197 GenerateV14XmlResourcesInDir(input_dir, output_dir, only_styles=True)
198 231
199 if options.stamp: 232 if options.stamp:
200 build_utils.Touch(options.stamp) 233 build_utils.Touch(options.stamp)
201 234
202 if __name__ == '__main__': 235 if __name__ == '__main__':
203 sys.exit(main(sys.argv)) 236 sys.exit(main(sys.argv))
204 237
OLDNEW
« no previous file with comments | « build/android/gyp/copy_v17_resources.py ('k') | build/android/gyp/generate_v14_resources.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698