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>
This commit is contained in:
copilot-swe-agent[bot] 2026-04-17 04:50:49 +00:00 committed by GitHub
parent cfb2e7566e
commit 96fc61bfd9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 122 additions and 29 deletions

View File

@ -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:

View File

@ -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('../..')

84
imgsrc/frame-dark.svg Normal file
View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="1024"
height="1024"
fill="none"
version="1.1"
id="svg13"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<g
filter="url(#a)"
id="g2">
<rect
width="824"
height="824"
x="100"
y="100"
fill="#1c1c1e"
rx="184"
id="rect1" />
<rect
width="824"
height="824"
x="100"
y="100"
fill="url(#b)"
rx="184"
id="rect2" />
</g>
<defs
id="defs13">
<linearGradient
id="b"
x1="512"
x2="512"
y1="100"
y2="924"
gradientUnits="userSpaceOnUse">
<stop
stop-color="#fff"
stop-opacity=".08"
id="stop10" />
<stop
offset="1"
stop-opacity="0"
id="stop11" />
</linearGradient>
<filter
id="a"
width="868"
height="868"
x="78"
y="89"
color-interpolation-filters="sRGB"
filterUnits="userSpaceOnUse">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood11" />
<feColorMatrix
in="SourceAlpha"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
id="feColorMatrix11" />
<feOffset
dy="11"
id="feOffset11" />
<feGaussianBlur
stdDeviation="11"
id="feGaussianBlur11" />
<feColorMatrix
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"
id="feColorMatrix12" />
<feBlend
in2="BackgroundImageFix"
result="effect1_dropShadow"
id="feBlend12" />
<feBlend
in="SourceGraphic"
in2="effect1_dropShadow"
result="shape"
id="feBlend13" />
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB