From 96fc61bfd9a8ea2a7e3ada69a4dea2784579845f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 04:50:49 +0000 Subject: [PATCH] Add dark mode frame SVG and update iconset generation for light/dark subdirectories Agent-Logs-Url: https://github.com/kovidgoyal/calibre/sessions/e4e53fa0-3fcf-4a89-aa8a-1f4829934bd2 Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com> --- bypy/macos/__main__.py | 2 +- icons/icns/make_iconsets.py | 65 +++++++++++++++------------- imgsrc/frame-dark.svg | 84 +++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 29 deletions(-) create mode 100644 imgsrc/frame-dark.svg diff --git a/bypy/macos/__main__.py b/bypy/macos/__main__.py index feab51c081..fe419175e5 100644 --- a/bypy/macos/__main__.py +++ b/bypy/macos/__main__.py @@ -373,7 +373,7 @@ class Freeze: c = join(self.build_dir, 'Contents') for x in ('Frameworks', 'MacOS', 'Resources'): os.makedirs(join(c, x)) - icons = glob.glob(join(CALIBRE_DIR, 'icons', 'icns', '*.iconset')) + icons = glob.glob(join(CALIBRE_DIR, 'icons', 'icns', 'light', '*.iconset')) if not icons: raise SystemExit('Failed to find icns format icons') for x in icons: diff --git a/icons/icns/make_iconsets.py b/icons/icns/make_iconsets.py index 1ae66e4ecc..48b9dc1974 100755 --- a/icons/icns/make_iconsets.py +++ b/icons/icns/make_iconsets.py @@ -19,6 +19,11 @@ sources = {'calibre':j(imgsrc, 'calibre.svg'), 'ebook-edit':j(imgsrc, 'tweak.svg if sys.argv[-1] == 'only-logo': sources = {'calibre':sources['calibre']} +frames = { + 'light': j(imgsrc, 'frame.svg'), + 'dark': j(imgsrc, 'frame-dark.svg'), +} + def render_svg(src, sz, dest): subprocess.check_call(['rsvg-convert', src, '-w', str(sz), '-h', str(sz), '-o', dest]) @@ -26,38 +31,42 @@ def render_svg(src, sz, dest): with tempfile.TemporaryDirectory() as tdir: - def render_frame(sz: int): - f = os.path.join(tdir, f'frame-{sz}.png') + def render_frame(mode: str, sz: int): + f = os.path.join(tdir, f'frame-{mode}-{sz}.png') if not os.path.exists(f): - render_svg(j(imgsrc, 'frame.svg'), sz, f) + render_svg(frames[mode], sz, f) return f - def render_framed(sz: int, iname: str, shrink_factor: float = 0.75): - frame = render_frame(sz) + def render_framed(mode: str, sz: int, iname: str, shrink_factor: float = 0.75): + frame = render_frame(mode, sz) icon = os.path.join(tdir, f'icon-{sz}.png') render_svg(src, int(shrink_factor * sz), icon) subprocess.check_call(f'convert {frame} {icon} -gravity center -compose over -composite {iname}'.split()) - for name, src in sources.items(): - iconset = name + '.iconset' - if os.path.exists(iconset): - shutil.rmtree(iconset) - os.mkdir(iconset) - os.chdir(iconset) - try: - for sz in (16, 32, 128, 256, 512, 1024): - iname = f'icon_{sz}x{sz}.png' - iname2x = f'icon_{sz // 2}x{sz // 2}@2x.png' - if sz < 128: - render_svg(src, sz, iname) - else: - render_framed(sz, iname) - if sz > 16: - shutil.copy2(iname, iname2x) - if sz > 512: - os.remove(iname) - for name in (iname, iname2x): - if os.path.exists(name): - subprocess.check_call(['optipng', '-o7', '-strip', 'all', name]) - finally: - os.chdir('..') + for mode in ('light', 'dark'): + subdir = mode + if not os.path.exists(subdir): + os.mkdir(subdir) + for name, src in sources.items(): + iconset = j(subdir, name + '.iconset') + if os.path.exists(iconset): + shutil.rmtree(iconset) + os.mkdir(iconset) + os.chdir(iconset) + try: + for sz in (16, 32, 128, 256, 512, 1024): + iname = f'icon_{sz}x{sz}.png' + iname2x = f'icon_{sz // 2}x{sz // 2}@2x.png' + if sz < 128: + render_svg(src, sz, iname) + else: + render_framed(mode, sz, iname) + if sz > 16: + shutil.copy2(iname, iname2x) + if sz > 512: + os.remove(iname) + for name in (iname, iname2x): + if os.path.exists(name): + subprocess.check_call(['optipng', '-o7', '-strip', 'all', name]) + finally: + os.chdir('../..') diff --git a/imgsrc/frame-dark.svg b/imgsrc/frame-dark.svg new file mode 100644 index 0000000000..377ea87ad0 --- /dev/null +++ b/imgsrc/frame-dark.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + +