maintenance-as-architecture
clone your own copy | download snapshot

Snapshots | iceberg

Inside this repository

unify_svg_strokes.py
text/x-python

Download raw (2.8 KB)

# -*- coding: utf-8 -*- #
"""
UNIFY SVG STROKES
=============

This plugin processes svg pictures to unify their stroke widths
"""
from __future__ import unicode_literals

import copy
import collections
import functools
import os.path
import re
import six

from xml.dom import minidom
from bs4 import BeautifulSoup
from pelican import signals


def harvest_images(path, context):
    # Set default value for 'IMAGE_PROCESS_DIR'.
    if 'UNIFIED_OUTPUT_DIR' not in context:
        context['UNIFIED_OUTPUT_DIR'] = 'unified'

    if 'UNIFIED_STROKE_WIDTH' not in context:
        context['UNIFIED_STROKE_WIDTH'] = '2px'

    with open(path, 'r+') as f:
        res = harvest_images_in_fragment(f, context)
        f.seek(0)
        f.truncate()
        f.write(res)


def harvest_images_in_fragment(fragment, settings):
    parser = settings.get("UNIFIED_PARSER", "html.parser")
    soup = BeautifulSoup(fragment, parser)

    for img in soup.find_all('img'):
        if os.path.splitext(img['src'])[1] == '.svg':
            process_img_tag(img, settings)

    return str(soup)

def process_img_tag(img, settings):
    process_dir = settings['UNIFIED_OUTPUT_DIR']
    url_path, filename = os.path.split(img['src'])
    base_url = os.path.join(url_path, process_dir)
    source = os.path.join(settings['PATH'], img['src'][1:])
    base_path = os.path.join(settings['OUTPUT_PATH'], base_url[1:])


    img['src'] = os.path.join(base_url, filename)
    destination = os.path.join(base_path, filename)

    unify_strokes(source, destination, settings['UNIFIED_STROKE_WIDTH'])


def set_vector_scale (node, width):
    if node.hasAttribute('style'):
        node.setAttribute('style', node.getAttribute('style') + ';vector-effect:non-scaling-stroke;stroke-width: {};'.format(width))
    else:
        node.setAttribute('style', 'vector-effect:non-scaling-stroke;stroke-width: {};'.format(width))

def unify_strokes (source, destination, width):
    path, _ = os.path.split(destination)
    try:
        os.makedirs(path)
    except OSError as e:
        if e.errno == 17:
            # Already exists
            pass

    # If original image is older than existing derivative, skip
    # processing to save time, unless user explicitely forced
    # image generation.
    if (not os.path.exists(destination) or
            os.path.getmtime(source) > os.path.getmtime(destination)):

        doc = minidom.parse(source)  # parseString also exists

        paths = doc.getElementsByTagName('path')

        for path in paths:
            set_vector_scale(path, width)

        lines = doc.getElementsByTagName('line')

        for line in lines:
            set_vector_scale(line, width)
    
        with open(destination, 'w') as o:
            doc.writexml(o)


def register():
    signals.content_written.connect(harvest_images)