예제 #1
0
def get_colorized_svg_image(filename, layers):
    """
    Open the given svg file and colorise all given layers (by id) to the given
    colour values. The given layers argument represents a dictionary that maps
    any given layer to the new fill colour, which is given as a hex-value,
    like #rrggbb.
    """
    # load xml (svg)
    xml = BeautifulSoup(open(filename), 'xml')

    # determine layer prefix (if any)
    prefix = xml.svg.get('data-prefix', '')
    if prefix != '':
        prefix += '_'

    # find all layers we need to colorise...
    for layer_id, instructions in layers.items():
        el = xml.find(id='%s%s' % (prefix, layer_id))
        if el is None:
            continue

        # assume a list of instructions
        if not isinstance(instructions, list):
            instructions = [instructions]

        style = parse_inline_style(el.get('style', ''))
        for instruction in instructions:
            # split attr:value
            instr = instruction.strip()
            p = instr.split(':')
            if len(p) == 1:
                attr = 'fill'
                value = instr
            elif len(p) == 2:
                attr = p[0]
                value = p[1]
            else:
                attr = None

            # skip instructions that we do not understand
            if attr is None:
                continue

            # skip attributes what we do not support
            if attr not in SUPPORTED_SVG_STYLE_OVERWRITES:
                continue

            # remove attribute if exists, for example 'fill' might be expressed
            # as an attribute or inline style. We will write this as inline
            # style, therefore we remove the corresponding attribute if it
            # exists...
            del el[attr]

            # if the value is hexadecimal, append a # to encode the correct
            # colour information if it is missing.
            if not value.startswith('#') and re.match(r'^[0-9a-fA-F]+$',
                                                      value):
                value = '#' + value

            # add to style
            style[attr] = value

        # update element's inline style
        el['style'] = encode_inline_style(style)

    # return changed content as xml. We should be safe from any code injection
    # here, since bs4 will re-build and escape all style attributes...
    return unicode(xml)
예제 #2
0
 def test_should_split_css_inline_style_by_rule(self):
     self.assertEqual({
         'fill': 'red',
         'stroke': '#efefef'
     }, parse_inline_style('  fill: red;  stroke: #efefef  '))
예제 #3
0
 def test_should_ignore_empty_rules(self):
     self.assertEqual({'fill': 'red'},
                      parse_inline_style('  fill: red;  stroke;;;  '))
예제 #4
0
 def test_should_return_empty_dict_for_empty_inline_style(self):
     self.assertEqual({}, parse_inline_style(''))