fix(splash): skip runtime title/version draw and use mantle background
Some checks failed
Build and Test / build (pull_request) Failing after 19m15s
Some checks failed
Build and Test / build (pull_request) Failing after 19m15s
The splash PNG already has the title and version baked in by generate-splash.py, but SplashScreen::splashImage() was drawing them again at position (6,75) which fell outside the rounded background rectangle (starts at 30,30). Skip runtime text rendering for Kindred Create while keeping the dev build warning. Also switch the splash background from Catppuccin Mocha base (#1e1e2e) to mantle (#181825) for a darker appearance and regenerate assets.
This commit is contained in:
@@ -34,53 +34,67 @@ except ImportError:
|
||||
|
||||
# Catppuccin Mocha colors
|
||||
COLORS = {
|
||||
'base': '#1e1e2e',
|
||||
'surface0': '#313244',
|
||||
'text': '#cdd6f4',
|
||||
'subtext0': '#a6adc8',
|
||||
'blue': '#89b4fa',
|
||||
'lavender': '#b4befe',
|
||||
"mantle": "#181825",
|
||||
"base": "#1e1e2e",
|
||||
"surface0": "#313244",
|
||||
"text": "#cdd6f4",
|
||||
"subtext0": "#a6adc8",
|
||||
"blue": "#89b4fa",
|
||||
"lavender": "#b4befe",
|
||||
}
|
||||
|
||||
|
||||
def hex_to_rgb(hex_color):
|
||||
"""Convert hex color to RGB tuple."""
|
||||
hex_color = hex_color.lstrip('#')
|
||||
hex_color = hex_color.lstrip("#")
|
||||
return tuple(int(hex_color[i : i + 2], 16) for i in (0, 2, 4))
|
||||
|
||||
|
||||
def create_rounded_rectangle(draw, bbox, radius, fill):
|
||||
"""Draw a rounded rectangle."""
|
||||
x1, y1, x2, y2 = bbox
|
||||
draw.rounded_rectangle(bbox, radius=radius, fill=fill)
|
||||
|
||||
|
||||
def load_svg_as_image(svg_path, width, height):
|
||||
"""Load an SVG file and convert to PIL Image at specified size."""
|
||||
if cairosvg:
|
||||
import io
|
||||
|
||||
png_data = cairosvg.svg2png(url=str(svg_path), output_width=width, output_height=height)
|
||||
return Image.open(io.BytesIO(png_data)).convert('RGBA')
|
||||
return Image.open(io.BytesIO(png_data)).convert("RGBA")
|
||||
else:
|
||||
# Fallback: try using inkscape command line
|
||||
import subprocess
|
||||
import tempfile
|
||||
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp:
|
||||
|
||||
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
|
||||
tmp_path = tmp.name
|
||||
try:
|
||||
subprocess.run([
|
||||
'inkscape', '-w', str(width), '-h', str(height),
|
||||
str(svg_path), '-o', tmp_path
|
||||
], check=True, capture_output=True)
|
||||
img = Image.open(tmp_path).convert('RGBA')
|
||||
subprocess.run(
|
||||
["inkscape", "-w", str(width), "-h", str(height), str(svg_path), "-o", tmp_path],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
img = Image.open(tmp_path).convert("RGBA")
|
||||
return img
|
||||
finally:
|
||||
if os.path.exists(tmp_path):
|
||||
os.unlink(tmp_path)
|
||||
|
||||
|
||||
def get_font(size, bold=False):
|
||||
"""Get a font, falling back to default if not available."""
|
||||
font_names = [
|
||||
'/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf' if bold else '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',
|
||||
'/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf' if bold else '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf',
|
||||
'/usr/share/fonts/TTF/DejaVuSans-Bold.ttf' if bold else '/usr/share/fonts/TTF/DejaVuSans.ttf',
|
||||
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
|
||||
if bold
|
||||
else "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
||||
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf"
|
||||
if bold
|
||||
else "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
|
||||
"/usr/share/fonts/TTF/DejaVuSans-Bold.ttf"
|
||||
if bold
|
||||
else "/usr/share/fonts/TTF/DejaVuSans.ttf",
|
||||
]
|
||||
for font_name in font_names:
|
||||
if os.path.exists(font_name):
|
||||
@@ -88,6 +102,7 @@ def get_font(size, bold=False):
|
||||
# Fallback to default
|
||||
return ImageFont.load_default()
|
||||
|
||||
|
||||
def create_splash(output_path, logo_path, width, height, version, freecad_version, scale=1):
|
||||
"""Create a splash screen image."""
|
||||
# Scale dimensions
|
||||
@@ -97,11 +112,11 @@ def create_splash(output_path, logo_path, width, height, version, freecad_versio
|
||||
padding = int(30 * scale)
|
||||
|
||||
# Create image with transparent background
|
||||
img = Image.new('RGBA', (w, h), (0, 0, 0, 0))
|
||||
img = Image.new("RGBA", (w, h), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# Draw rounded rectangle background
|
||||
bg_color = hex_to_rgb(COLORS['base'])
|
||||
bg_color = hex_to_rgb(COLORS["mantle"])
|
||||
create_rounded_rectangle(draw, (padding, padding, w - padding, h - padding), radius, bg_color)
|
||||
|
||||
# Load and place logo
|
||||
@@ -125,7 +140,7 @@ def create_splash(output_path, logo_path, width, height, version, freecad_versio
|
||||
title_width = title_bbox[2] - title_bbox[0]
|
||||
title_x = (w - title_width) // 2
|
||||
title_y = int(250 * scale)
|
||||
draw.text((title_x, title_y), title, fill=hex_to_rgb(COLORS['text']), font=title_font)
|
||||
draw.text((title_x, title_y), title, fill=hex_to_rgb(COLORS["text"]), font=title_font)
|
||||
|
||||
# Draw version string
|
||||
version_font = get_font(int(12 * scale))
|
||||
@@ -134,12 +149,15 @@ def create_splash(output_path, logo_path, width, height, version, freecad_versio
|
||||
version_width = version_bbox[2] - version_bbox[0]
|
||||
version_x = (w - version_width) // 2
|
||||
version_y = title_y + int(35 * scale)
|
||||
draw.text((version_x, version_y), version_str, fill=hex_to_rgb(COLORS['subtext0']), font=version_font)
|
||||
draw.text(
|
||||
(version_x, version_y), version_str, fill=hex_to_rgb(COLORS["subtext0"]), font=version_font
|
||||
)
|
||||
|
||||
# Save
|
||||
img.save(output_path, 'PNG')
|
||||
img.save(output_path, "PNG")
|
||||
print(f"Created: {output_path}")
|
||||
|
||||
|
||||
def create_about(output_path, logo_path, width, height, scale=1):
|
||||
"""Create an about dialog image."""
|
||||
# Scale dimensions
|
||||
@@ -147,7 +165,7 @@ def create_about(output_path, logo_path, width, height, scale=1):
|
||||
h = int(height * scale)
|
||||
|
||||
# Create image
|
||||
img = Image.new('RGBA', (w, h), hex_to_rgb(COLORS['base']) + (255,))
|
||||
img = Image.new("RGBA", (w, h), hex_to_rgb(COLORS["base"]) + (255,))
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# Load and place logo
|
||||
@@ -163,18 +181,19 @@ def create_about(output_path, logo_path, width, height, scale=1):
|
||||
print(f"Warning: Could not load logo: {e}")
|
||||
|
||||
# Save
|
||||
img.save(output_path, 'PNG')
|
||||
img.save(output_path, "PNG")
|
||||
print(f"Created: {output_path}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Generate Kindred Create splash screens')
|
||||
parser.add_argument('--version', default='0.1.0', help='Kindred Create version')
|
||||
parser.add_argument('--freecad-version', default='1.0.0', help='FreeCAD version')
|
||||
parser = argparse.ArgumentParser(description="Generate Kindred Create splash screens")
|
||||
parser.add_argument("--version", default="0.1.0", help="Kindred Create version")
|
||||
parser.add_argument("--freecad-version", default="1.0.0", help="FreeCAD version")
|
||||
args = parser.parse_args()
|
||||
|
||||
script_dir = Path(__file__).parent
|
||||
logo_path = script_dir / 'kindred-logo.svg'
|
||||
icons_dir = script_dir.parent.parent / 'src' / 'Gui' / 'Icons'
|
||||
logo_path = script_dir / "kindred-logo.svg"
|
||||
icons_dir = script_dir.parent.parent / "src" / "Gui" / "Icons"
|
||||
|
||||
if not logo_path.exists():
|
||||
print(f"Error: Logo not found at {logo_path}")
|
||||
@@ -182,33 +201,31 @@ def main():
|
||||
|
||||
# Create splash screens (600x400 as per spec)
|
||||
create_splash(
|
||||
icons_dir / 'kindredcreatesplash.png',
|
||||
icons_dir / "kindredcreatesplash.png",
|
||||
logo_path,
|
||||
600, 400,
|
||||
600,
|
||||
400,
|
||||
args.version,
|
||||
args.freecad_version,
|
||||
scale=1
|
||||
scale=1,
|
||||
)
|
||||
|
||||
# Create 2x version for HiDPI
|
||||
create_splash(
|
||||
icons_dir / 'kindredcreatesplash_2x.png',
|
||||
icons_dir / "kindredcreatesplash_2x.png",
|
||||
logo_path,
|
||||
600, 400,
|
||||
600,
|
||||
400,
|
||||
args.version,
|
||||
args.freecad_version,
|
||||
scale=2
|
||||
scale=2,
|
||||
)
|
||||
|
||||
# Create about image
|
||||
create_about(
|
||||
icons_dir / 'kindredcreateabout.png',
|
||||
logo_path,
|
||||
400, 200,
|
||||
scale=1
|
||||
)
|
||||
create_about(icons_dir / "kindredcreateabout.png", logo_path, 400, 200, scale=1)
|
||||
|
||||
print("\nSplash screen generation complete!")
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
@@ -360,9 +360,6 @@ QPixmap SplashScreen::splashImage()
|
||||
fontExe.setPointSizeF(20.0);
|
||||
QFontMetrics metricExe(fontExe);
|
||||
int l = QtTools::horizontalAdvance(metricExe, title);
|
||||
if (title == QLatin1String("Kindred Create")) {
|
||||
// For Kindred Create splash, we draw the title as part of the dynamic rendering
|
||||
}
|
||||
int w = splash_image.width();
|
||||
int h = splash_image.height();
|
||||
|
||||
@@ -386,6 +383,8 @@ QPixmap SplashScreen::splashImage()
|
||||
QColor color(QString::fromStdString(tc->second));
|
||||
if (color.isValid()) {
|
||||
painter.setPen(color);
|
||||
if (title != QLatin1String("Kindred Create")) {
|
||||
// Kindred Create's splash PNG already contains the title and version
|
||||
painter.setFont(fontExe);
|
||||
if (title != QLatin1String("FreeCAD")) {
|
||||
// FreeCAD's Splashscreen already contains the EXE name, no need to draw it
|
||||
@@ -393,6 +392,7 @@ QPixmap SplashScreen::splashImage()
|
||||
}
|
||||
painter.setFont(fontVer);
|
||||
painter.drawText(x + (l + 235), y - 7, version);
|
||||
}
|
||||
QColor warningColor(QString::fromStdString(wc->second));
|
||||
if (suffix == QLatin1String("dev") && warningColor.isValid()) {
|
||||
fontVer.setPointSizeF(14.0);
|
||||
|
||||
Reference in New Issue
Block a user