108
108
if match is not None:
109
109
smartsprites_info = match.group(1)
110
110
parameters = self._parseCommentParameters(match.group(1))
111
# Currently, only a single combined image is supported.
111
112
if parameters['sprite-ref'] == group_name:
112
113
filename = self._getSpriteImagePath(
113
114
rule, url_prefix_substitutions)
114
self.sprites.append(dict(filename=filename, rule=rule))
115
self.sprite_info.append(dict(filename=filename, rule=rule))
117
if len(self.sprite_info) == 0:
118
raise AssertionError(
119
"No sprite-ref comments for group %r found" % group_name)
116
121
def _getSpriteImagePath(self, rule, url_prefix_substitutions=None):
117
122
"""Convert the url path to a filesystem path."""
143
148
def combineImages(self, css_dir):
144
149
"""Copy all the sprites into a single PIL image."""
145
for sprite in self.sprites:
146
filename = os.path.join(css_dir, sprite['filename'])
147
sprite['image'] = Image.open(filename)
149
if len(self.sprites) == 0:
150
raise AssertionError("No images found.")
154
for sprite in self.sprites:
155
width, height = sprite['image'].size
156
max_width = max(width, max_width)
157
total_height += height
159
# Separate each image with lots of whitespace.
151
# Open all the sprite images.
154
total_sprite_height = 0
155
for sprite in self.sprite_info:
156
abs_filename = os.path.join(css_dir, sprite['filename'])
157
sprite_images[sprite['filename']] = Image.open(abs_filename)
158
width, height = sprite_images[sprite['filename']].size
159
max_sprite_width = max(width, max_sprite_width)
160
total_sprite_height += height
162
# The combined image is the height of all the sprites
163
# plus the margin between each of them.
160
164
combined_image_height = (
161
total_height + (self.margin * len(self.sprites)))
162
transparent = (0,0,0,0)
165
total_sprite_height + (self.margin * len(self.sprite_info) - 1))
166
transparent = (0, 0, 0, 0)
163
167
combined_image = Image.new(
165
size=(max_width, combined_image_height),
169
size=(max_sprite_width, combined_image_height),
166
170
color=transparent)
172
# Paste each sprite into the combined image.
170
for index, sprite in enumerate(self.sprites):
175
for index, sprite in enumerate(self.sprite_info):
176
sprite_image = sprite_images[sprite['filename']]
172
178
position = [0, y]
173
combined_image.paste(sprite['image'], tuple(position))
179
combined_image.paste(sprite_image, tuple(position))
174
180
# An icon in a vertically combined image can be repeated
175
181
# horizontally, but we have to repeat it in the combined
176
182
# image so that we don't repeat white space.
177
183
if sprite['rule'].style.backgroundRepeat == 'repeat-x':
178
width = sprite['image'].size[0]
179
for x_position in range(width, max_width, width):
184
width = sprite_image.size[0]
185
for x_position in range(width, max_sprite_width, width):
180
186
position[0] = x_position
181
combined_image.paste(sprite['image'], tuple(position))
187
combined_image.paste(sprite_image, tuple(position))
183
189
print >> sys.stderr, (
184
190
"Error with image file %s" % sprite['filename'])
187
193
# element. Therefore, it subtracts the position of the
188
194
# sprite in the file to move it to the top of the element.
189
195
positions[sprite['filename']] = (0, -y)
190
y += sprite['image'].size[1] + self.margin
196
y += sprite_image.size[1] + self.margin
198
# If there is an exception earlier, these attributes will remain None.
192
199
self.positions = positions
193
200
self.combined_image = combined_image