The surface turns dark with light labels and cables and a faint light outline round Java's icons; documentation rectangles become a tint of their colour and texts are drawn towards light; the mode buttons use Java's pictures freed from their grey ground (tools/dark-pictures/make.py); native controls follow color-scheme; the desktop's program windows paint through Java-look tokens whose light values are Java's own. The exported image and the report keep Java's colours. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
62 lines
2.4 KiB
Python
62 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""The mode buttons' pictures for the editor's dark scheme (packages/editor/src/assets/modes/*_dunkel.png).
|
|
|
|
Java's pictures are 50 x 50 buttons: a frame and a vertical grey gradient (light blue and flat when the mode is
|
|
on) around the icon. On a dark button that ground would stand as a light tile, so it is freed: the outer ring of
|
|
RING pixels goes, and from there every pixel within GROUND of its row's ground colour (the gradient is row by row)
|
|
becomes transparent, flooding inwards; a pixel up to EDGE from it (the icon's edge, blended with the grey) keeps its
|
|
colour and fades with its likeness. Needs Pillow; run from the repository's root:
|
|
|
|
python3 tools/dark-pictures/make.py
|
|
"""
|
|
|
|
from collections import deque
|
|
from pathlib import Path
|
|
|
|
from PIL import Image
|
|
|
|
MODES = Path(__file__).resolve().parents[2] / 'packages/editor/src/assets/modes'
|
|
RING = 3
|
|
GROUND = 8
|
|
EDGE = 48
|
|
|
|
|
|
def freed(picture: Image.Image) -> Image.Image:
|
|
image = picture.convert('RGBA')
|
|
width, height = image.size
|
|
pixels = image.load()
|
|
ground = [pixels[RING, y] for y in range(height)]
|
|
for y in range(RING):
|
|
ground[y] = ground[RING]
|
|
for y in range(height - RING, height):
|
|
ground[y] = ground[height - RING - 1]
|
|
seen = set()
|
|
queue = deque()
|
|
for x in range(width):
|
|
for y in range(height):
|
|
if x < RING or y < RING or x >= width - RING or y >= height - RING:
|
|
pixels[x, y] = (0, 0, 0, 0)
|
|
seen.add((x, y))
|
|
queue.extend([(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)])
|
|
while queue:
|
|
x, y = queue.popleft()
|
|
if (x, y) in seen or not (0 <= x < width and 0 <= y < height):
|
|
continue
|
|
seen.add((x, y))
|
|
colour = pixels[x, y]
|
|
distance = max(abs(colour[index] - ground[y][index]) for index in range(3))
|
|
if distance <= GROUND:
|
|
pixels[x, y] = (*colour[:3], 0)
|
|
queue.extend([(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)])
|
|
elif distance <= EDGE:
|
|
pixels[x, y] = (*colour[:3], min(255, int(255 * (distance - GROUND) / (EDGE - GROUND))))
|
|
return image
|
|
|
|
|
|
if __name__ == '__main__':
|
|
for source in sorted(MODES.glob('*.png')):
|
|
if source.stem.endswith('_dunkel'):
|
|
continue
|
|
freed(Image.open(source)).save(source.with_name(f'{source.stem}_dunkel.png'))
|
|
print(source.with_name(f'{source.stem}_dunkel.png').name)
|