Release v0.4.0: add screen capture and annotation editor
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
"""Development only: pip install resvg-py==0.5.0 Pillow.
|
||||
Render the pinned Lucide SVG originals into embedded, multi-resolution Windows icons.
|
||||
"""
|
||||
from pathlib import Path
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
import resvg_py
|
||||
import re
|
||||
import struct
|
||||
|
||||
root = Path(__file__).resolve().parents[1] / 'resources' / 'icons' / 'lucide'
|
||||
names = ['circle-dot', 'arrow-up-right', 'undo-2', 'copy', 'x', 'redo-2', 'highlighter', 'palette', 'pencil', 'slash', 'square', 'circle', 'ellipse', 'type', 'a-large-small']
|
||||
for name in names:
|
||||
svg = (root / f'{name}.svg').read_text(encoding='utf-8')
|
||||
for variant, color in [('normal', '#334155'), ('active', '#2563eb'), ('disabled', '#94a3b8')]:
|
||||
png = resvg_py.svg_to_bytes(svg_string=svg.replace('currentColor', color), width=256, height=256)
|
||||
im = Image.open(BytesIO(png)).convert('RGBA')
|
||||
im.save(root / f'{name}-{variant}.ico', sizes=[(s, s) for s in (16,20,22,24,28,32,40,44,48,56,64,96,128,256)])
|
||||
|
||||
# Small local visual QA sheet of the actual downloaded paths.
|
||||
preview = Image.new('RGB', (len(names)*60, 72), '#f8fafc')
|
||||
for i, name in enumerate(names):
|
||||
icon = Image.open(root / f'{name}-normal.ico').convert('RGBA').resize((32,32),Image.Resampling.LANCZOS)
|
||||
preview.paste(icon,(14+i*60,20),icon)
|
||||
preview.save(root / 'preview.png')
|
||||
|
||||
# Cursor uses the same Lucide pencil, with a white outline for dark screenshots.
|
||||
paths = '\n'.join(re.findall(r'<path\b[^>]+/>', (root / 'pencil.svg').read_text(encoding='utf-8')))
|
||||
cursor_svg = f'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 28 28" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<g stroke="white" stroke-width="4">{paths}</g><g stroke="#334155" stroke-width="2">{paths}</g></svg>'''
|
||||
cursor_png = resvg_py.svg_to_bytes(svg_string=cursor_svg, width=256, height=256)
|
||||
cursor_image = Image.open(BytesIO(cursor_png)).convert('RGBA')
|
||||
buffer = BytesIO()
|
||||
cursor_image.save(buffer, format='ICO', bitmap_format='bmp', sizes=[(s,s) for s in (32,48,64,96)])
|
||||
cursor = bytearray(buffer.getvalue())
|
||||
struct.pack_into('<H', cursor, 2, 2) # CUR instead of ICO
|
||||
for index in range(struct.unpack_from('<H', cursor, 4)[0]):
|
||||
entry = 6 + index * 16
|
||||
size = cursor[entry] or 256
|
||||
# Drawing point is the tip of the pencil, not the center of its image.
|
||||
struct.pack_into('<HH', cursor, entry+4, round(size*4/28), round(size*24/28))
|
||||
(root / 'pencil.cur').write_bytes(cursor)
|
||||
@@ -10,6 +10,12 @@ try {
|
||||
foreach ($process in $config) { if (-not $process.WaitForExit(10000)) { throw 'Close the configurator before updating.' } }
|
||||
Copy-Item -LiteralPath (Join-Path $root 'build\staged\KSwitcher.Config.exe') -Destination (Join-Path $root 'build\KSwitcher.Config.exe') -Force
|
||||
Copy-Item -LiteralPath (Join-Path $root 'build\staged\KSwitcher.exe') -Destination $exe -Force
|
||||
Start-Process -FilePath $exe -WindowStyle Hidden
|
||||
$eventName = 'Local\KSwitcher.Update.Started.' + [guid]::NewGuid().ToString('N')
|
||||
$started = [System.Threading.EventWaitHandle]::new($false, [System.Threading.EventResetMode]::ManualReset, $eventName)
|
||||
try {
|
||||
$newProcess = Start-Process -FilePath $exe -ArgumentList "--update-ready-event=$eventName" -WorkingDirectory (Split-Path $exe) -WindowStyle Hidden -PassThru
|
||||
if (-not $started.WaitOne(10000)) { throw 'KSwitcher did not confirm startup within 10 seconds.' }
|
||||
if ($newProcess.WaitForExit(1000)) { throw "KSwitcher exited after startup (code $($newProcess.ExitCode))." }
|
||||
} finally { $started.Dispose() }
|
||||
'OK' | Set-Content -LiteralPath (Join-Path $root 'build\update-result.txt')
|
||||
} catch { $_.Exception.Message | Set-Content -LiteralPath (Join-Path $root 'build\update-result.txt'); exit 1 }
|
||||
|
||||
Reference in New Issue
Block a user