~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/services/spriteutils.py

  • Committer: Edwin Grubbs
  • Date: 2010-02-09 03:16:27 UTC
  • mto: This revision was merged to the branch mainline in revision 10304.
  • Revision ID: edwin.grubbs@canonical.com-20100209031627-p6si8xyew85qkfty
Added tests. Moved to lp.services.

Show diffs side-by-side

added added

removed removed

Lines of Context:
100
100
        smartsprites_exp = re.compile(
101
101
            r'/\*+([^*]*sprite-ref: [^*]*)\*/')
102
102
        self.css_object = cssutils.parseFile(css_template_file)
103
 
        self.sprites = []
 
103
        self.sprite_info = []
104
104
        for rule in self.css_object:
105
105
            if rule.cssText is None:
106
106
                continue
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))
 
116
 
 
117
        if len(self.sprite_info) == 0:
 
118
            raise AssertionError(
 
119
                "No sprite-ref comments for group %r found" % group_name)
115
120
 
116
121
    def _getSpriteImagePath(self, rule, url_prefix_substitutions=None):
117
122
        """Convert the url path to a filesystem path."""
142
147
 
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)
148
 
 
149
 
        if len(self.sprites) == 0:
150
 
            raise AssertionError("No images found.")
151
 
 
152
 
        max_width = 0
153
 
        total_height = 0
154
 
        for sprite in self.sprites:
155
 
            width, height = sprite['image'].size
156
 
            max_width = max(width, max_width)
157
 
            total_height += height
158
 
 
159
 
        # Separate each image with lots of whitespace.
 
150
 
 
151
        # Open all the sprite images.
 
152
        sprite_images = {}
 
153
        max_sprite_width = 0
 
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
 
161
 
 
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(
164
168
            mode='RGBA',
165
 
            size=(max_width, combined_image_height),
 
169
            size=(max_sprite_width, combined_image_height),
166
170
            color=transparent)
167
171
 
 
172
        # Paste each sprite into the combined image.
168
173
        y = 0
169
174
        positions = {}
170
 
        for index, sprite in enumerate(self.sprites):
 
175
        for index, sprite in enumerate(self.sprite_info):
 
176
            sprite_image = sprite_images[sprite['filename']]
171
177
            try:
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))
182
188
            except:
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
191
197
 
 
198
        # If there is an exception earlier, these attributes will remain None.
192
199
        self.positions = positions
193
200
        self.combined_image = combined_image
194
201
 
224
231
            background-image: url(combined_image_url_path)
225
232
            background-position: 0px 2344px
226
233
        """
227
 
        for sprite in self.sprites:
 
234
        for sprite in self.sprite_info:
228
235
            rule = sprite['rule']
229
236
            rule.style.backgroundImage = 'url(%s)' % combined_image_url_path
230
237
            position = self.positions[sprite['filename']]