File indexing completed on 2026-11-09 10:47:39
0001
0002 """Render the devcloud SVG favicon to a conventional multi-size ICO file."""
0003 import argparse
0004 from pathlib import Path
0005 import shutil
0006 import subprocess
0007 import tempfile
0008 from urllib.request import urlopen
0009 from xml.etree import ElementTree
0010
0011 from PIL import Image
0012
0013 LOGO_SOURCE = 'https://wiki.bnl.gov/EPIC/images/9/90/EPIC-logo_black.svg'
0014
0015
0016 def refresh_outline(public):
0017 with urlopen(LOGO_SOURCE, timeout=15) as source:
0018 root = ElementTree.fromstring(source.read())
0019 path = root.find('.//*[@id="path1122"]')
0020 if path is None:
0021 raise ValueError('Official logo lowercase e outline is missing')
0022 (public / 'favicon.svg').write_text(
0023 '<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 96 96">\n'
0024 ' <title>ePIC devcloud</title>\n'
0025 f' <!-- Lowercase e outline from {LOGO_SOURCE} -->\n'
0026 f' <path fill="#ed2024" transform="translate(6 83)" d="{path.attrib["d"]}"/>\n'
0027 '</svg>\n')
0028
0029
0030 def main():
0031 parser = argparse.ArgumentParser(description=__doc__)
0032 parser.add_argument('--chromium', default=shutil.which('chromium'))
0033 parser.add_argument('--refresh-outline', action='store_true',
0034 help='Fetch the original lowercase e from the collaboration logo')
0035 args = parser.parse_args()
0036 if not args.chromium:
0037 parser.error('Chromium is required')
0038 public = Path(__file__).resolve().parent.parent / 'public'
0039 if args.refresh_outline:
0040 refresh_outline(public)
0041 with tempfile.TemporaryDirectory(prefix='devcloud-favicon-') as work:
0042 work = Path(work)
0043 png = work / 'favicon.png'
0044 subprocess.run([
0045 args.chromium, '--headless', '--no-sandbox', '--disable-gpu',
0046 '--hide-scrollbars', '--no-first-run', '--no-default-browser-check',
0047 '--default-background-color=00000000', '--force-device-scale-factor=1',
0048 '--window-size=256,256', f'--user-data-dir={work / "profile"}',
0049 f'--screenshot={png}', (public / 'favicon.svg').as_uri(),
0050 ], check=True, timeout=30, stdout=subprocess.DEVNULL)
0051 with Image.open(png) as image:
0052 if image.size != (256, 256):
0053 raise ValueError(f'Unexpected render size: {image.size}')
0054 image.save(public / 'favicon.ico', sizes=[(16, 16), (32, 32), (48, 48)])
0055 print(f'Wrote {public / "favicon.ico"}')
0056
0057
0058 if __name__ == '__main__':
0059 main()