101 lines
3.9 KiB
Swift
101 lines
3.9 KiB
Swift
#!/usr/bin/env swift
|
|
// Generiert das RemminaMac App-Icon (Dracula-Terminal) als PNG-Set + .iconset.
|
|
// Aufruf: swift scripts/RenderIcon.swift <output-dir>
|
|
// Braucht nur macOS-Bordmittel (AppKit). Kein Netzwerk, keine Deps.
|
|
import AppKit
|
|
import Foundation
|
|
|
|
let outDir = CommandLine.arguments.count > 1 ? CommandLine.arguments[1] : "/tmp/RemminaMac.iconset"
|
|
try? FileManager.default.createDirectory(atPath: outDir, withIntermediateDirectories: true)
|
|
|
|
// Dracula-Palette
|
|
func c(_ hex: String, _ alpha: CGFloat = 1) -> NSColor {
|
|
var v: UInt64 = 0
|
|
Scanner(string: hex).scanHexInt64(&v)
|
|
return NSColor(red: CGFloat((v >> 16) & 0xFF) / 255,
|
|
green: CGFloat((v >> 8) & 0xFF) / 255,
|
|
blue: CGFloat(v & 0xFF) / 255, alpha: alpha)
|
|
}
|
|
let bg1 = c("3A3D4F"), bg2 = c("23242F"), bar = c("44475A")
|
|
let green = c("50FA7B"), pink = c("FF79C6"), purple = c("BD93F9")
|
|
let red = c("FF5555"), yellow = c("F1FA8C")
|
|
|
|
func drawIcon(size: CGFloat) -> NSImage {
|
|
let img = NSImage(size: NSSize(width: size, height: size))
|
|
img.lockFocus()
|
|
let s = size / 1024.0 // Skalierung relativ zu 1024er-Master
|
|
NSGraphicsContext.current?.imageInterpolation = .high
|
|
|
|
// Hintergrund: abgerundetes Quadrat mit Verlauf
|
|
let rect = NSRect(x: 0, y: 0, width: size, height: size)
|
|
let radius = 232 * s
|
|
let path = NSBezierPath(roundedRect: rect, xRadius: radius, yRadius: radius)
|
|
let grad = NSGradient(colors: [bg1, bg2])!
|
|
grad.draw(in: path, angle: 90)
|
|
// feine Kontur
|
|
bar.withAlphaComponent(0.9).setStroke()
|
|
path.lineWidth = max(2, 6 * s)
|
|
path.stroke()
|
|
|
|
// Dezenter Glow hinter der Glyphe
|
|
let glow = NSShadow()
|
|
glow.shadowColor = purple.withAlphaComponent(0.55)
|
|
glow.shadowBlurRadius = 90 * s
|
|
glow.shadowOffset = .zero
|
|
|
|
// Traffic-Lights (Fenster-Look)
|
|
for (i, col) in [red, yellow, green].enumerated() {
|
|
let r = 40 * s
|
|
let cx = CGFloat(150 + i * 108) * s
|
|
let cy = size - 158.0 * s
|
|
col.setFill()
|
|
NSBezierPath(ovalIn: NSRect(x: cx - r, y: cy - r, width: 2 * r, height: 2 * r)).fill()
|
|
}
|
|
|
|
// Prompt „>" + Block-Cursor (Menlo Bold)
|
|
let fontSize: CGFloat = 470 * s
|
|
let font: NSFont = NSFont(name: "Menlo-Bold", size: fontSize)
|
|
?? NSFont.monospacedSystemFont(ofSize: fontSize, weight: .bold)
|
|
let attrs: [NSAttributedString.Key: Any] = [.font: font, .foregroundColor: green]
|
|
let glyph = NSAttributedString(string: ">", attributes: attrs)
|
|
let gw = glyph.size()
|
|
|
|
// Cursor-Block rechts vom „>"
|
|
let gap = 44 * s
|
|
let cursorW = 128 * s, cursorH = 96 * s
|
|
let totalW = gw.width + gap + cursorW
|
|
let startX = (size - totalW) / 2
|
|
let baseY = size * 0.30
|
|
|
|
NSGraphicsContext.saveGraphicsState()
|
|
NSGraphicsContext.current?.cgContext.setShadow(offset: .zero, blur: 90 * s, color: purple.withAlphaComponent(0.55).cgColor)
|
|
glyph.draw(at: NSPoint(x: startX, y: baseY))
|
|
NSGraphicsContext.restoreGraphicsState()
|
|
|
|
let cursor = NSBezierPath(roundedRect: NSRect(x: startX + gw.width + gap, y: baseY + 30 * s, width: cursorW, height: cursorH), xRadius: 14 * s, yRadius: 14 * s)
|
|
pink.setFill()
|
|
cursor.fill()
|
|
|
|
img.unlockFocus()
|
|
return img
|
|
}
|
|
|
|
func save(_ img: NSImage, _ name: String) {
|
|
guard let tiff = img.tiffRepresentation,
|
|
let rep = NSBitmapImageRep(data: tiff),
|
|
let png = rep.representation(using: .png, properties: [:]) else {
|
|
fputs("FEHLER bei \(name)\n", stderr); exit(1)
|
|
}
|
|
try! png.write(to: URL(fileURLWithPath: "\(outDir)/\(name)"))
|
|
}
|
|
|
|
// iconset: je Größe 1x + 2x
|
|
for base in [16, 32, 128, 256, 512] {
|
|
save(drawIcon(size: CGFloat(base)), "icon_\(base)x\(base).png")
|
|
save(drawIcon(size: CGFloat(base * 2)), "icon_\(base)x\(base)@2x.png")
|
|
}
|
|
// Vorschau in groß
|
|
try? FileManager.default.createDirectory(atPath: "/tmp", withIntermediateDirectories: true)
|
|
save(drawIcon(size: 512), "RemminaMac-preview-tmp.png")
|
|
print("iconset fertig: \(outDir)")
|