A4

Merge lp:~andrea.corbellini/a4/cleanup-1 into lp:a4

Proposed by Andrea Corbellini
Status: Merged
Merged at revision: 10
Proposed branch: lp:~andrea.corbellini/a4/cleanup-1
Merge into: lp:a4
Diff against target: 200 lines (+82/-60)
1 file modified
a4lib/presentation.py (+82/-60)
To merge this branch: bzr merge lp:~andrea.corbellini/a4/cleanup-1
Reviewer Review Type Date Requested Status
Andrea Gasparini Approve
Review via email: mp+26962@code.launchpad.net

Description of the change

This branch is the first step to clean up the code, and focuses to the a4lib.presentation module. Here are the details of what I have done:

1. PEP 8: http://www.python.org/dev/peps/pep-0008/
2. PEP 257: http://www.python.org/dev/peps/pep-0257/
3. I've removed mutable objects from the default values of methods. In other words, I've changed all "def m(arg=[])" to "def m(arg=None)".
4. I've also refactored some code to enhance readability.

However, I couldn't clean up two methods: Presentation._reduce_matrix_list and Presentation._get_rotation_from_matrix_list. At a quick glance, I couldn't understand what do they do. There are some comments, but are unclear. The doc string should really be improved.

Also, I can't understand why the arguments are optional: every time these two methods are called, they do get the argument.

Finally, I think that we should create a class for the transformation matrices.

To post a comment you must log in.
Revision history for this message
Andrea Gasparini (gaspa) wrote :

IMO it's ok.
Just that numpy.dot() has to be used instead of "*" operator in reduce_matrix_list(). But I guess we can merge your changes, and then correct this.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'a4lib/presentation.py'
2--- a4lib/presentation.py 2010-06-01 22:03:43 +0000
3+++ a4lib/presentation.py 2010-06-07 15:46:20 +0000
4@@ -3,26 +3,26 @@
5
6 """Code to deal with SVG images."""
7
8+import json
9+import math
10 import re
11-import json
12 import rsvg
13-import math
14-
15-from numpy import array, dot
16 from glib import GError
17 from lxml import etree
18-
19-## FIXME: get these from the svg itself, we currently care only about "svg:"
20-## namespace, the others can be ignored.
21+from numpy import array
22+
23+
24+# FIXME Get these from the SVG itself, we currently care only about "svg:"
25+# namespace, the others can be ignored.
26 nsmap = {
27- 'sodipodi': 'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd',
28- 'cc': 'http://web.resource.org/cc/',
29- 'svg': 'http://www.w3.org/2000/svg',
30- 'dc': 'http://purl.org/dc/elements/1.1/',
31- 'xlink': 'http://www.w3.org/1999/xlink',
32- 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
33- 'inkscape': 'http://www.inkscape.org/namespaces/inkscape'}
34-
35+ 'sodipodi': 'http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd',
36+ 'cc': 'http://web.resource.org/cc/',
37+ 'svg': 'http://www.w3.org/2000/svg',
38+ 'dc': 'http://purl.org/dc/elements/1.1/',
39+ 'xlink': 'http://www.w3.org/1999/xlink',
40+ 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
41+ 'inkscape': 'http://www.inkscape.org/namespaces/inkscape'
42+ }
43
44 class PresentationError(StandardError):
45 """Error raised when an operation with an image fails."""
46@@ -43,8 +43,9 @@
47
48 self.svgtree = etree.parse(file_name)
49
50- ## get all the text strings contained by our metadata
51- xpath_query = "//svg:metadata[@id='a4-presentation-information']/text()"
52+ # Get all the text strings contained by our metadata.
53+ xpath_query = (
54+ "//svg:metadata[@id='a4-presentation-information']/text()")
55 info_strings = self.svgtree.xpath(xpath_query, namespaces=nsmap)
56 data = u''.join(info_strings)
57 try:
58@@ -58,44 +59,56 @@
59 self.render_cairo = self._svg_handler.render_cairo
60
61 def _handle_transform(self, target_element=None):
62- """ Handle svg transform tags and build up a list of tranformations
63- given in matrix()'s terms"""
64+ """Handle SVG transform tags and build a list of tranformations."""
65 matrix_list = []
66 while target_element is not None:
67 transform_string = target_element.attrib.get('transform')
68- if transform_string:
69- matches = re.search(
70- "matrix\((.*?),(.*?),(.*?),(.*?),(.*?),(.*?)\)",
71- transform_string)
72- if matches:
73- transform_matrix = [float(matches.group(i))
74- for i in xrange(1, 7)]
75- matrix_list.append(transform_matrix)
76- matches = re.search("translate\((.*?),(.*?)\)",
77- transform_string)
78- if matches:
79- transform_matrix = [1, 0, 0, 1, float(matches.group(1)),
80- float(matches.group(2))]
81- matrix_list.append(transform_matrix)
82- matches = re.search("scale\((.*?),(.*?)\)", transform_string)
83- if matches:
84- transform_matrix = [float(matches.group(1)), 0, 0,
85- float(matches.group(2)), 0, 0]
86- matrix_list.append(transform_matrix)
87- matches = re.search("rotate\((.*?)\)", transform_string)
88- if matches:
89- # [ cos(a) sin(a) -sin(a) cos(a) 0 0].
90- a = math.radians(int(matches.group(1)))
91- transform_matrix = [math.cos(a), math.sin(a),
92- - math.sin(a), math.cos(a), 0, 0]
93- matrix_list.append(transform_matrix)
94 target_element = target_element.getparent()
95+ if not transform_string:
96+ # This element doesn't contain a transform tag.
97+ continue
98+
99+ # Look for a transformation matrix.
100+ matches = re.search(
101+ 'matrix\((.*?),(.*?),(.*?),(.*?),(.*?),(.*?)\)',
102+ transform_string)
103+ if matches:
104+ transform_matrix = [
105+ float(matches.group(i)) for i in xrange(1, 7)]
106+ matrix_list.append(transform_matrix)
107+
108+ # Look for a translation.
109+ matches = re.search(
110+ 'translate\((.*?),(.*?)\)', transform_string)
111+ if matches:
112+ transform_matrix = [
113+ 1, 0, 0, 1, float(matches.group(1)),
114+ float(matches.group(2))]
115+ matrix_list.append(transform_matrix)
116+
117+ # Look for a scale factor.
118+ matches = re.search("scale\((.*?),(.*?)\)", transform_string)
119+ if matches:
120+ transform_matrix = [
121+ float(matches.group(1)), 0, 0,
122+ float(matches.group(2)), 0, 0]
123+ matrix_list.append(transform_matrix)
124+
125+ # Look for a rotation.
126+ matches = re.search("rotate\((.*?)\)", transform_string)
127+ if matches:
128+ angle = math.radians(int(matches.group(1)))
129+ transform_matrix = [
130+ math.cos(angle), math.sin(angle), -math.sin(angle),
131+ math.cos(angle), 0, 0]
132+ matrix_list.append(transform_matrix)
133+
134 return matrix_list
135
136- def _reduce_matrix_list(self, mt_list=[]):
137- """ Take a list of matrix(), as given by SVG code, and returns
138+ def _reduce_matrix_list(self, mt_list=None):
139+ """Take a list of matrixes, as given by SVG code, and returns
140 a single numpy.array() representing the whole transformation"""
141- if mt_list == []:
142+ if not mt_list:
143 return None
144 ### reduce the matrix_list to only one.
145 ### get the rotation angle (degree?radiants?)
146@@ -108,33 +121,42 @@
147 return result
148
149 def _get_rotation_from_matrix_list(self, matrix=None):
150- """ Calculate rotation angle from the transformation matrix """
151- if matrix == None:
152+ """Calculate rotation angle from the transformation matrix."""
153+ if not matrix:
154 return 0
155 scalefactor = math.sqrt(matrix[0][0] ** 2 + matrix[0][1] ** 2)
156- tmp_angle = math.asin(matrix[0][1] / scalefactor)
157+ angle = math.asin(matrix[0][1] / scalefactor)
158 if matrix[0][0] < 0:
159- return math.pi - tmp_angle
160+ return math.pi - angle
161 else:
162- return tmp_angle
163+ return angle
164
165 def get_item_properties_by_id(self, item_id):
166- """ Returns some interesting properties ( bounding box, rotation angle,
167- etc...) given an SVG's element id """
168+ """Returns some properties of the SVG element with the given id.
169+
170+ The properties returned are:
171+ * the width and the height of the element;
172+ * its position;
173+ * the transformations and the rotations.
174+ """
175 try:
176- target_element = self.svgtree.xpath("//svg:*[@id='%s']" %
177- item_id, namespaces=nsmap)
178+ target_element = self.svgtree.xpath(
179+ "//svg:*[@id='{0}']".format(item_id), namespaces=nsmap)
180 except etree.XPathEvalError:
181 raise PresentationError('Can find the requested item')
182+
183 properties = {}
184 if len(target_element) > 0:
185- properties['width'] = float(target_element[0].attrib.get('width'))
186- properties['height'] = float(target_element[0].attrib.get('height'))
187+ properties['width'] = float(
188+ target_element[0].attrib.get('width'))
189+ properties['height'] = float(
190+ target_element[0].attrib.get('height'))
191 properties['x'] = float(target_element[0].attrib.get('x'))
192 properties['y'] = float(target_element[0].attrib.get('y'))
193 properties['transform'] = self._reduce_matrix_list(
194 self._handle_transform(target_element[0]))
195- if properties['transform'] != []:
196+
197+ if properties['transform']:
198 properties['rotation'] = self._get_rotation_from_matrix_list(
199 properties['transform'])
200 else:

Subscribers

People subscribed via source and target branches