Add dark mode icons to calibre.icns

Doesn't actually work. The good lord only knows why not. I have wasted
enough of my life on Apple's idiocies.
This commit is contained in:
Kovid Goyal 2026-04-17 13:25:21 +05:30
parent 8833c84290
commit 92fc9eb5c8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 30 additions and 13 deletions

2
.gitignore vendored
View File

@ -35,7 +35,7 @@
/resources/mozilla-ca-certs.pem
/resources/user-agent-data.json
/resources/piper-voices.json
/icons/icns/*.iconset
/icons/icns/*/*.iconset
/setup/installer/windows/calibre/build.log
/setup/pyqt_enums
/tags

View File

@ -1,5 +1,5 @@
# Requires installation of XCode 16.2 and
# python3 -m pip install certifi html5lib
# python3 -m pip install certifi html5lib icnsutil
vm_name 'macos-calibre'
root '/Users/Shared/calibre-build'

View File

@ -19,6 +19,8 @@ import zipfile
from functools import partial, reduce
from itertools import repeat
import icnsutil
from bypy.constants import OUTPUT_DIR, PREFIX, PYTHON, python_major_minor_version
from bypy.constants import SRC as CALIBRE_DIR
from bypy.freeze import extract_extension_modules, fix_pycryptodome, freeze_python, is_package_dir, path_to_freeze_dir
@ -49,6 +51,20 @@ EXPECTED_ARCHES = {'x86_64', 'arm64'}
MINIMUM_SYSTEM_VERSION = '14.0.0'
def generate_icns(light_iconset: str, dark_iconset: str, output_path: str) -> None:
def add_iconset(icns, path):
for img in os.listdir(path):
if img.endswith('.png'):
icns.add_media(file=os.path.join(path, img))
dark_icns = icnsutil.IcnsFile()
add_iconset(dark_icns, dark_iconset)
dark_icns.write(output_path, toc=True)
light_icns = icnsutil.IcnsFile()
add_iconset(light_icns, light_iconset)
light_icns.add_media(icnsutil.IcnsType.key_from_readable('dark'), file=output_path)
light_icns.write(output_path, toc=True)
def compile_launcher_lib(contents_dir, base, pyver, inc_dir):
print('\tCompiling calibre_launcher.dylib')
env, env_vals = [], []
@ -223,6 +239,7 @@ class Freeze:
@flush
def run_tests(self):
print('Running tests...', flush=True)
self.test_runner(join(self.contents_dir, 'MacOS', 'calibre-debug'), self.contents_dir)
@flush
@ -377,9 +394,10 @@ class Freeze:
if not icons:
raise SystemExit('Failed to find icns format icons')
for x in icons:
subprocess.check_call([
'iconutil', '-c', 'icns', x, '-o', join(
self.resources_dir, basename(x).partition('.')[0] + '.icns')])
output_icns = join(self.resources_dir, basename(x).partition('.')[0] + '.icns')
xd = x.replace('/light/', '/dark/')
assert x != xd
generate_icns(x, xd, output_icns)
for helpers in (self.helpers_dir,):
os.makedirs(helpers)
cdir = dirname(helpers)

View File

@ -41,12 +41,11 @@ with tempfile.TemporaryDirectory() as tdir:
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())
subprocess.check_call(f'magick {frame} {icon} -gravity center -compose over -composite {iname}'.split())
for mode in ('light', 'dark'):
subdir = mode
if not os.path.exists(subdir):
os.mkdir(subdir)
os.makedirs(subdir, exist_ok=True)
for name, src in sources.items():
iconset = j(subdir, name + '.iconset')
if os.path.exists(iconset):
@ -54,19 +53,19 @@ with tempfile.TemporaryDirectory() as tdir:
os.mkdir(iconset)
os.chdir(iconset)
try:
for sz in (16, 32, 128, 256, 512, 1024):
for sz in (16, 32, 64, 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)
subprocess.check_call(['optipng', '-o7', '-strip', 'all', iname])
if sz > 16:
shutil.copy2(iname, iname2x)
if sz > 512:
if sz > 512 or sz == 64:
os.remove(iname)
for name in (iname, iname2x):
if os.path.exists(name):
subprocess.check_call(['optipng', '-o7', '-strip', 'all', name])
if sz == 128:
os.remove(iname2x)
finally:
os.chdir('../..')