def _sprite_map(g, **kwargs):
    """
    Generates a sprite map from the files matching the glob pattern.
    Uses the keyword-style arguments passed in to control the placement.
    """
    g = StringValue(g).value

    if not Image:
        raise Exception("Images manipulation require PIL")

    if g in sprite_maps:
        sprite_maps[glob]['*'] = datetime.datetime.now()
    elif '..' not in g:  # Protect against going to prohibited places...
        vertical = (kwargs.get('direction', 'vertical') == 'vertical')
        offset_x = NumberValue(kwargs.get('offset_x', 0))
        offset_y = NumberValue(kwargs.get('offset_y', 0))
        repeat = StringValue(kwargs.get('repeat', 'no-repeat'))
        position = NumberValue(kwargs.get('position', 0))
        dst_color = kwargs.get('dst_color')
        src_color = kwargs.get('src_color')
        if position and position > -1 and position < 1:
            position.units = {'%': _units_weights.get('%', 1), '_': '%'}
        spacing = kwargs.get('spacing', 0)
        if isinstance(spacing, ListValue):
            spacing = [int(NumberValue(v).value) for n, v in spacing.items()]
        else:
            spacing = [int(NumberValue(spacing).value)]
        spacing = (spacing * 4)[:4]

        if callable(STATIC_ROOT):
            rfiles = files = sorted(STATIC_ROOT(g))
        else:
            glob_path = os.path.join(STATIC_ROOT, g)
            files = glob.glob(glob_path)
            files = sorted((f, None) for f in files)
            rfiles = [(f[len(STATIC_ROOT):], s) for f, s in files]

        if not files:
            log.error("Nothing found at '%s'", glob_path)
            return StringValue(None)

        times = []
        for file, storage in files:
            try:
                d_obj = storage.modified_time(file)
                times.append(int(time.mktime(d_obj.timetuple())))
            except:
                times.append(int(os.path.getmtime(file)))

        map_name = os.path.normpath(
            os.path.dirname(g)).replace('\\', '_').replace('/', '_')
        key = list(zip(*files)[0]) + times + [repr(kwargs)]
        key = map_name + '-' + base64.urlsafe_b64encode(
            hashlib.md5(repr(key)).digest()).rstrip('=').replace('-', '_')
        asset_file = key + '.png'
        asset_path = os.path.join(ASSETS_ROOT, asset_file)

        if os.path.exists(asset_path + '.cache'):
            asset, map, sizes = pickle.load(open(asset_path + '.cache'))
            sprite_maps[asset] = map
        else:
            images = tuple(Image.open(storage.open(file)) if storage is not None else Image.open(file) for file, storage in files)
            names = tuple(os.path.splitext(
                os.path.basename(file))[0] for file, storage in files)
            positions = []
            spacings = []
            tot_spacings = []
            for name in names:
                name = name.replace('-', '_')
                _position = kwargs.get(name + '_position')
                if _position is None:
                    _position = position
                else:
                    _position = NumberValue(_position)
                    if _position and _position > -1 and _position < 1:
                        _position.units = {'%':
                                           _units_weights.get('%', 1), '_': '%'}
                positions.append(_position)
                _spacing = kwargs.get(name + '_spacing')
                if _spacing is None:
                    _spacing = spacing
                else:
                    if isinstance(_spacing, ListValue):
                        _spacing = [int(NumberValue(
                            v).value) for n, v in _spacing.items()]
                    else:
                        _spacing = [int(NumberValue(_spacing).value)]
                    _spacing = (_spacing * 4)[:4]
                spacings.append(_spacing)
                if _position and _position.unit != '%':
                    if vertical:
                        if _position > 0:
                            tot_spacings.append((_spacing[0], _spacing[
                                1], _spacing[2], _spacing[3] + _position))
                    else:
                        if _position > 0:
                            tot_spacings.append((_spacing[0] + _position,
                                                 _spacing[1], _spacing[2], _spacing[3]))
                else:
                    tot_spacings.append(_spacing)
            sizes = tuple(image.size for image in images)

            _spacings = zip(*tot_spacings)
            if vertical:
                width = max(
                    zip(*sizes)[0]) + max(_spacings[1]) + max(_spacings[3])
                height = sum(
                    zip(*sizes)[1]) + sum(_spacings[0]) + sum(_spacings[2])
            else:
                width = sum(
                    zip(*sizes)[0]) + sum(_spacings[1]) + sum(_spacings[3])
                height = max(
                    zip(*sizes)[1]) + max(_spacings[0]) + max(_spacings[2])

            new_image = Image.new(
                mode='RGBA',
                size=(width, height),
                color=(0, 0, 0, 0)
            )

            offsets_x = []
            offsets_y = []
            offset = 0
            for i, image in enumerate(images):
                spacing = spacings[i]
                position = positions[i]
                if vertical:
                    if position and position.unit == '%':
                        x = width * position.value - \
                            (spacing[3] + sizes[i][1] + spacing[1])
                    elif position.value < 0:
                        x = width + position.value - \
                            (spacing[3] + sizes[i][1] + spacing[1])
                    else:
                        x = position.value
                    offset += spacing[0]
                    new_image.paste(image, (int(x + spacing[3]), offset))
                    offsets_x.append(x)
                    offsets_y.append(offset - spacing[0])
                    offset += sizes[i][1] + spacing[2]
                else:
                    if position and position.unit == '%':
                        y = height * position.value - \
                            (spacing[0] + sizes[i][1] + spacing[2])
                    elif position.value < 0:
                        y = height + position.value - \
                            (spacing[0] + sizes[i][1] + spacing[2])
                    else:
                        y = position.value
                    offset += spacing[3]
                    new_image.paste(image, (offset, int(y + spacing[0])))
                    offsets_x.append(offset - spacing[3])
                    offsets_y.append(y)
                    offset += sizes[i][0] + spacing[1]

            if dst_color:
                src_color = ColorValue(
                    src_color).value[:3] if src_color else (0, 0, 0)
                dst_color = list(ColorValue(dst_color).value[:3])
                pixdata = new_image.load()
                for y in xrange(new_image.size[1]):
                    for x in xrange(new_image.size[0]):
                        if pixdata[x, y][:3] == src_color:
                            pixdata[x,
                                    y] = tuple(dst_color + [pixdata[x, y][3]])

            try:
                new_image.save(asset_path)
            except IOError:
                log.exception("Error while saving image")
            filetime = int(time.mktime(datetime.datetime.now().timetuple()))

            url = '%s%s?_=%s' % (ASSETS_URL, asset_file, filetime)
            asset = 'url("%s") %s' % (escape(url), repeat)
            # Use the sorted list to remove older elements (keep only 500
            # objects):
            if len(sprite_maps) > 1000:
                for a in sorted(sprite_maps, key=lambda a: sprite_maps[a]['*'], reverse=True)[500:]:
                    del sprite_maps[a]
            # Add the new object:
            map = dict(zip(names, zip(sizes, rfiles, offsets_x, offsets_y)))
            map['*'] = datetime.datetime.now()
            map['*f*'] = asset_file
            map['*k*'] = key
            map['*n*'] = map_name
            map['*t*'] = filetime
            pickle.dump((asset, map, zip(files, sizes)), open(
                asset_path + '.cache', 'w'))
            sprite_maps[asset] = map
        for file, size in sizes:
            sprite_images[file] = size
    ret = StringValue(asset)
    return ret
def _sprite_map ( g , ** kwargs ) : g = StringValue ( g ) . value if not Image : raise Exception ( "Images manipulation require PIL" ) if g in sprite_maps : sprite_maps [ glob ] [ '*' ] = datetime . datetime . now ( ) elif '..' not in g : vertical = ( kwargs . get ( 'direction' , 'vertical' ) == 'vertical' ) offset_x = NumberValue ( kwargs . get ( 'offset_x' , 0 ) ) offset_y = NumberValue ( kwargs . get ( 'offset_y' , 0 ) ) repeat = StringValue ( kwargs . get ( 'repeat' , 'no-repeat' ) ) position = NumberValue ( kwargs . get ( 'position' , 0 ) ) dst_color = kwargs . get ( 'dst_color' ) src_color = kwargs . get ( 'src_color' ) if position and position > - 1 and position < 1 : position . units = { '%' : _units_weights . get ( '%' , 1 ) , '_' : '%' } spacing = kwargs . get ( 'spacing' , 0 ) if isinstance ( spacing , ListValue ) : spacing = [ int ( NumberValue ( v ) . value ) for n , v in spacing . items ( ) ] else : spacing = [ int ( NumberValue ( spacing ) . value ) ] spacing = ( spacing * 4 ) [ : 4 ] if callable ( STATIC_ROOT ) : rfiles = files = sorted ( STATIC_ROOT ( g ) ) else : glob_path = os . path . join ( STATIC_ROOT , g ) files = glob . glob ( glob_path ) files = sorted ( ( f , None ) for f in files ) rfiles = [ ( f [ len ( STATIC_ROOT ) : ] , s ) for f , s in files ] if not files : log . error ( "Nothing found at '%s'" , glob_path ) return StringValue ( None ) times = [ ] for file , storage in files : try : d_obj = storage . modified_time ( file ) times . append ( int ( time . mktime ( d_obj . timetuple ( ) ) ) ) except : times . append ( int ( os . path . getmtime ( file ) ) ) map_name = os . path . normpath ( os . path . dirname ( g ) ) . replace ( '\\' , '_' ) . replace ( '/' , '_' ) key = list ( zip ( * files ) [ 0 ] ) + times + [ repr ( kwargs ) ] key = map_name + '-' + base64 . urlsafe_b64encode ( hashlib . md5 ( repr ( key ) ) . digest ( ) ) . rstrip ( '=' ) . replace ( '-' , '_' ) asset_file = key + '.png' asset_path = os . path . join ( ASSETS_ROOT , asset_file ) if os . path . exists ( asset_path + '.cache' ) : asset , map , sizes = pickle . load ( open ( asset_path + '.cache' ) ) sprite_maps [ asset ] = map else : images = tuple ( Image . open ( storage . open ( file ) ) if storage is not None else Image . open ( file ) for file , storage in files ) names = tuple ( os . path . splitext ( os . path . basename ( file ) ) [ 0 ] for file , storage in files ) positions = [ ] spacings = [ ] tot_spacings = [ ] for name in names : name = name . replace ( '-' , '_' ) _position = kwargs . get ( name + '_position' ) if _position is None : _position = position else : _position = NumberValue ( _position ) if _position and _position > - 1 and _position < 1 : _position . units = { '%' : _units_weights . get ( '%' , 1 ) , '_' : '%' } positions . append ( _position ) _spacing = kwargs . get ( name + '_spacing' ) if _spacing is None : _spacing = spacing else : if isinstance ( _spacing , ListValue ) : _spacing = [ int ( NumberValue ( v ) . value ) for n , v in _spacing . items ( ) ] else : _spacing = [ int ( NumberValue ( _spacing ) . value ) ] _spacing = ( _spacing * 4 ) [ : 4 ] spacings . append ( _spacing ) if _position and _position . unit != '%' : if vertical : if _position > 0 : tot_spacings . append ( ( _spacing [ 0 ] , _spacing [ 1 ] , _spacing [ 2 ] , _spacing [ 3 ] + _position ) ) else : if _position > 0 : tot_spacings . append ( ( _spacing [ 0 ] + _position , _spacing [ 1 ] , _spacing [ 2 ] , _spacing [ 3 ] ) ) else : tot_spacings . append ( _spacing ) sizes = tuple ( image . size for image in images ) _spacings = zip ( * tot_spacings ) if vertical : width = max ( zip ( * sizes ) [ 0 ] ) + max ( _spacings [ 1 ] ) + max ( _spacings [ 3 ] ) height = sum ( zip ( * sizes ) [ 1 ] ) + sum ( _spacings [ 0 ] ) + sum ( _spacings [ 2 ] ) else : width = sum ( zip ( * sizes ) [ 0 ] ) + sum ( _spacings [ 1 ] ) + sum ( _spacings [ 3 ] ) height = max ( zip ( * sizes ) [ 1 ] ) + max ( _spacings [ 0 ] ) + max ( _spacings [ 2 ] ) new_image = Image . new ( mode = 'RGBA' , size = ( width , height ) , color = ( 0 , 0 , 0 , 0 ) ) offsets_x = [ ] offsets_y = [ ] offset = 0 for i , image in enumerate ( images ) : spacing = spacings [ i ] position = positions [ i ] if vertical : if position and position . unit == '%' : x = width * position . value - ( spacing [ 3 ] + sizes [ i ] [ 1 ] + spacing [ 1 ] ) elif position . value < 0 : x = width + position . value - ( spacing [ 3 ] + sizes [ i ] [ 1 ] + spacing [ 1 ] ) else : x = position . value offset += spacing [ 0 ] new_image . paste ( image , ( int ( x + spacing [ 3 ] ) , offset ) ) offsets_x . append ( x ) offsets_y . append ( offset - spacing [ 0 ] ) offset += sizes [ i ] [ 1 ] + spacing [ 2 ] else : if position and position . unit == '%' : y = height * position . value - ( spacing [ 0 ] + sizes [ i ] [ 1 ] + spacing [ 2 ] ) elif position . value < 0 : y = height + position . value - ( spacing [ 0 ] + sizes [ i ] [ 1 ] + spacing [ 2 ] ) else : y = position . value offset += spacing [ 3 ] new_image . paste ( image , ( offset , int ( y + spacing [ 0 ] ) ) ) offsets_x . append ( offset - spacing [ 3 ] ) offsets_y . append ( y ) offset += sizes [ i ] [ 0 ] + spacing [ 1 ] if dst_color : src_color = ColorValue ( src_color ) . value [ : 3 ] if src_color else ( 0 , 0 , 0 ) dst_color = list ( ColorValue ( dst_color ) . value [ : 3 ] ) pixdata = new_image . load ( ) for y in xrange ( new_image . size [ 1 ] ) : for x in xrange ( new_image . size [ 0 ] ) : if pixdata [ x , y ] [ : 3 ] == src_color : pixdata [ x , y ] = tuple ( dst_color + [ pixdata [ x , y ] [ 3 ] ] ) try : new_image . save ( asset_path ) except IOError : log . exception ( "Error while saving image" ) filetime = int ( time . mktime ( datetime . datetime . now ( ) . timetuple ( ) ) ) url = '%s%s?_=%s' % ( ASSETS_URL , asset_file , filetime ) asset = 'url("%s") %s' % ( escape ( url ) , repeat ) if len ( sprite_maps ) > 1000 : for a in sorted ( sprite_maps , key = lambda a : sprite_maps [ a ] [ '*' ] , reverse = True ) [ 500 : ] : del sprite_maps [ a ] map = dict ( zip ( names , zip ( sizes , rfiles , offsets_x , offsets_y ) ) ) map [ '*' ] = datetime . datetime . now ( ) map [ '*f*' ] = asset_file map [ '*k*' ] = key map [ '*n*' ] = map_name map [ '*t*' ] = filetime pickle . dump ( ( asset , map , zip ( files , sizes ) ) , open ( asset_path + '.cache' , 'w' ) ) sprite_maps [ asset ] = map for file , size in sizes : sprite_images [ file ] = size ret = StringValue ( asset ) return ret
Generates a sprite map from the files matching the glob pattern.
    Uses the keyword-style arguments passed in to control the placement.