multi-shape.py

In web/At f362d60Copy the commit ID

f362d60History

Preview

Code2.9 KiB
"""Compare two- and three-solid favicons using the original geometry."""
from pathlib import Path
from copy import deepcopy
import sys
import subprocess
import xml.etree.ElementTree as E

ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))
from source.logo import render, NS

logo = E.fromstring(render(False))
scene = next(e for e in logo if e.tag == NS + 'svg')
GROUPS = {e.get('aria-label').lower(): e for e in scene}
BOUNDS = {'sphere': (-382.5, -244.25799, 235, 235), 'pyramid': (-232.5, -375, 315, 308.75), 'cube': (-82.5, -235.34, 270, 300.34), 'cylinder': (162.5, -382.5, 210, 337.5)}
OPTIONS = {
    'three-cylinder': [('cylinder', 26, 6, 22), ('sphere', 5, 20, 26), ('cube', 32, 27, 27)],
    'three-cylinder-color': [('cylinder', 26, 6, 22), ('sphere', 5, 20, 26), ('cube', 32, 27, 27)],
    'two-shapes': [('sphere', 5, 19, 28), ('cube', 30, 17, 29)],
    'three-shapes': [('pyramid', 16, 6, 32), ('sphere', 5, 29, 26), ('cube', 32, 27, 27)],
    'three-shapes-color': [('pyramid', 16, 6, 32), ('sphere', 5, 29, 26), ('cube', 32, 27, 27)],
}
art = ROOT / 'art/favicon'
art.mkdir(parents=True, exist_ok=True)
previews = ROOT / 'previews/favicon'
for name, solids in OPTIONS.items():
    root = E.Element(NS + 'svg', {'width': '64', 'height': '64', 'viewBox': '0 0 64 64', 'role': 'img', 'aria-label': 'KIT '+name.replace('-', ' ')})
    root.append(deepcopy(logo.find(NS + 'defs')))
    E.SubElement(root, NS + 'rect', {'width': '64', 'height': '64', 'rx': '14', 'fill': '#0067ed'})
    for shape, x, y, width in solids:
        bx, by, bw, bh = BOUNDS[shape]
        scale = width / bw
        outer = E.SubElement(root, NS + 'g', {'transform': f'translate({x} {y}) scale({scale}) translate({-bx} {-by})'})
        group = deepcopy(GROUPS[shape])
        for face in group:
            if face.tag in [NS + 'path', NS + 'circle']:
                if name.endswith('color'):
                    face.set('stroke', 'white')
                    face.set('stroke-width', str(.8 / scale))
                else:
                    face.set('fill', 'white')
                    face.set('stroke', '#0067ed')
                    face.set('stroke-width', str(1.5 / scale))
                face.set('stroke-linejoin', 'round')
        outer.append(group)
    defs = root.find(NS + 'defs')
    if not name.endswith('color'):
        root.remove(defs)
    else:
        used = ' '.join(v for child in list(root)[2:] for e in child.iter() for v in e.attrib.values())
        for gradient in list(defs):
            if 'url(#'+gradient.get('id')+')' not in used:
                defs.remove(gradient)
    svg = art / (name+'.svg')
    svg.write_text(E.tostring(root, encoding='unicode')+'\n')
    for size in [16, 32, 48]:
        subprocess.run(['rsvg-convert', '-w', str(size), '-h', str(size), '-o', str(previews/f'{name}-{size}.png'), str(svg)], check=True)
print('Built two-shape and three-shape favicons at 16, 32, and 48 pixels.')

Files