Add GrowthLapse app bundle and icon
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>de</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>GrowthLapse</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>GrowthLapse</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>GrowthLapse.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>de.mike-i386.GrowthLapse</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>GrowthLapse</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict>
|
||||
<key>Resources/GrowthLapse.icns</key>
|
||||
<data>
|
||||
G4b+0pcQtmuC7+3xzqOoSKZ6TdM=
|
||||
</data>
|
||||
</dict>
|
||||
<key>files2</key>
|
||||
<dict>
|
||||
<key>Resources/GrowthLapse.icns</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
oKK6OTT0Y0tD1lvaxWNP1djCSVl/FaaE8s+cm0CEg50=
|
||||
</data>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^Resources/</key>
|
||||
<true/>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^[^/]+$</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 808 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 510 KiB |
@@ -0,0 +1,127 @@
|
||||
import AppKit
|
||||
import Foundation
|
||||
|
||||
let output = URL(fileURLWithPath: CommandLine.arguments.dropFirst().first ?? "dist/GrowthLapse.iconset")
|
||||
try FileManager.default.createDirectory(at: output, withIntermediateDirectories: true)
|
||||
|
||||
struct IconFile {
|
||||
let name: String
|
||||
let size: Int
|
||||
}
|
||||
|
||||
let files = [
|
||||
IconFile(name: "icon_16x16.png", size: 16),
|
||||
IconFile(name: "icon_16x16@2x.png", size: 32),
|
||||
IconFile(name: "icon_32x32.png", size: 32),
|
||||
IconFile(name: "icon_32x32@2x.png", size: 64),
|
||||
IconFile(name: "icon_128x128.png", size: 128),
|
||||
IconFile(name: "icon_128x128@2x.png", size: 256),
|
||||
IconFile(name: "icon_256x256.png", size: 256),
|
||||
IconFile(name: "icon_256x256@2x.png", size: 512),
|
||||
IconFile(name: "icon_512x512.png", size: 512),
|
||||
IconFile(name: "icon_512x512@2x.png", size: 1024),
|
||||
]
|
||||
|
||||
func drawIcon(size: Int) throws -> Data {
|
||||
let rep = NSBitmapImageRep(
|
||||
bitmapDataPlanes: nil,
|
||||
pixelsWide: size,
|
||||
pixelsHigh: size,
|
||||
bitsPerSample: 8,
|
||||
samplesPerPixel: 4,
|
||||
hasAlpha: true,
|
||||
isPlanar: false,
|
||||
colorSpaceName: .deviceRGB,
|
||||
bytesPerRow: 0,
|
||||
bitsPerPixel: 0
|
||||
)!
|
||||
|
||||
NSGraphicsContext.saveGraphicsState()
|
||||
NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: rep)
|
||||
let scale = CGFloat(size) / 1024
|
||||
let canvas = NSRect(x: 0, y: 0, width: CGFloat(size), height: CGFloat(size))
|
||||
NSColor.clear.setFill()
|
||||
canvas.fill()
|
||||
|
||||
func rect(_ x: CGFloat, _ y: CGFloat, _ w: CGFloat, _ h: CGFloat) -> NSRect {
|
||||
NSRect(x: x * scale, y: y * scale, width: w * scale, height: h * scale)
|
||||
}
|
||||
|
||||
let bg = NSBezierPath(roundedRect: rect(72, 72, 880, 880), xRadius: 210 * scale, yRadius: 210 * scale)
|
||||
bg.addClip()
|
||||
let gradient = NSGradient(colors: [
|
||||
NSColor(calibratedRed: 0.06, green: 0.35, blue: 0.90, alpha: 1.0),
|
||||
NSColor(calibratedRed: 0.10, green: 0.72, blue: 0.58, alpha: 1.0)
|
||||
])!
|
||||
gradient.draw(in: canvas, angle: 38)
|
||||
|
||||
NSColor(calibratedWhite: 1.0, alpha: 0.16).setFill()
|
||||
NSBezierPath(ovalIn: rect(560, 74, 520, 520)).fill()
|
||||
NSBezierPath(ovalIn: rect(-120, 520, 440, 440)).fill()
|
||||
|
||||
NSGraphicsContext.restoreGraphicsState()
|
||||
NSGraphicsContext.saveGraphicsState()
|
||||
NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: rep)
|
||||
|
||||
let shadow = NSShadow()
|
||||
shadow.shadowColor = NSColor.black.withAlphaComponent(0.24)
|
||||
shadow.shadowBlurRadius = 34 * scale
|
||||
shadow.shadowOffset = NSSize(width: 0, height: -10 * scale)
|
||||
shadow.set()
|
||||
|
||||
for (index, item) in [
|
||||
rect(218, 250, 410, 520),
|
||||
rect(306, 214, 410, 520),
|
||||
rect(394, 178, 410, 520)
|
||||
].enumerated() {
|
||||
let frame = NSBezierPath(roundedRect: item, xRadius: 54 * scale, yRadius: 54 * scale)
|
||||
NSColor(calibratedWhite: 1, alpha: index == 2 ? 0.95 : 0.46).setFill()
|
||||
frame.fill()
|
||||
NSColor(calibratedWhite: 1, alpha: 0.95).setStroke()
|
||||
frame.lineWidth = 10 * scale
|
||||
frame.stroke()
|
||||
}
|
||||
|
||||
shadow.shadowColor = .clear
|
||||
shadow.set()
|
||||
|
||||
let photo = NSBezierPath(roundedRect: rect(430, 214, 338, 436), xRadius: 36 * scale, yRadius: 36 * scale)
|
||||
NSColor(calibratedRed: 0.07, green: 0.16, blue: 0.25, alpha: 1).setFill()
|
||||
photo.fill()
|
||||
|
||||
NSColor(calibratedRed: 0.72, green: 0.92, blue: 1.0, alpha: 1).setFill()
|
||||
NSBezierPath(ovalIn: rect(552, 438, 94, 94)).fill()
|
||||
let body = NSBezierPath(roundedRect: rect(504, 292, 190, 150), xRadius: 82 * scale, yRadius: 82 * scale)
|
||||
body.fill()
|
||||
|
||||
NSColor(calibratedWhite: 1, alpha: 0.96).setStroke()
|
||||
let curve = NSBezierPath()
|
||||
curve.move(to: NSPoint(x: 210 * scale, y: 270 * scale))
|
||||
curve.curve(
|
||||
to: NSPoint(x: 822 * scale, y: 760 * scale),
|
||||
controlPoint1: NSPoint(x: 360 * scale, y: 312 * scale),
|
||||
controlPoint2: NSPoint(x: 618 * scale, y: 620 * scale)
|
||||
)
|
||||
curve.lineWidth = 38 * scale
|
||||
curve.lineCapStyle = .round
|
||||
curve.stroke()
|
||||
|
||||
for point in [(210, 270), (420, 390), (620, 590), (822, 760)] {
|
||||
NSColor(calibratedWhite: 1, alpha: 1).setFill()
|
||||
NSBezierPath(ovalIn: rect(CGFloat(point.0 - 34), CGFloat(point.1 - 34), 68, 68)).fill()
|
||||
NSColor(calibratedRed: 0.08, green: 0.47, blue: 0.78, alpha: 1).setFill()
|
||||
NSBezierPath(ovalIn: rect(CGFloat(point.0 - 18), CGFloat(point.1 - 18), 36, 36)).fill()
|
||||
}
|
||||
|
||||
NSGraphicsContext.restoreGraphicsState()
|
||||
|
||||
guard let data = rep.representation(using: .png, properties: [:]) else {
|
||||
throw NSError(domain: "GrowthLapseIcon", code: 1)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
for file in files {
|
||||
let data = try drawIcon(size: file.size)
|
||||
try data.write(to: output.appendingPathComponent(file.name))
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.5 MiB |