1#!/usr/bin/env swift
2// Generates SophaxChat app icon: 1024×1024 PNG
3// Run: swift make_icon.swift
4
5import CoreGraphics
6import CoreText
7import Foundation
8import ImageIO
9
10let size = 1024
11let ctx = CGContext(
12 data: nil,
13 width: size, height: size,
14 bitsPerComponent: 8, bytesPerRow: 0,
15 space: CGColorSpaceCreateDeviceRGB(),
16 bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue
17)!
18
19let s = CGFloat(size)
20
21// ---------------------------------------------------------------------------
22// Background gradient: dark indigo → deep purple
23// ---------------------------------------------------------------------------
24let grad = CGGradient(
25 colorsSpace: CGColorSpaceCreateDeviceRGB(),
26 colors: [
27 CGColor(red: 0.07, green: 0.05, blue: 0.18, alpha: 1),
28 CGColor(red: 0.25, green: 0.08, blue: 0.42, alpha: 1),
29 ] as CFArray,
30 locations: [0, 1]
31)!
32ctx.drawLinearGradient(grad,
33 start: CGPoint(x: 0, y: s),
34 end: CGPoint(x: s, y: 0),
35 options: [])
36
37// ---------------------------------------------------------------------------
38// Three horizontal strokes — centered on canvas
39// Matches the hand-drawn three-line mark (slightly organic angles)
40// ---------------------------------------------------------------------------
41
42ctx.setStrokeColor(CGColor(red: 1, green: 1, blue: 1, alpha: 0.95))
43ctx.setLineCap(.round)
44
45let lineW: CGFloat = 500 // stroke length
46let lx0 = (s - lineW) / 2 // left start X
47let lx1 = lx0 + lineW // right end X
48let lineThick: CGFloat = 62 // stroke width
49let gap: CGFloat = 148 // vertical gap between line centers
50
51// CG y-up: center of the group sits exactly at canvas center
52// Total group height = 2 * gap = 296 → lines span ±148 around center
53let groupCY = s / 2 // 512 — true canvas center
54
55// Line 1 (top) — slight upward tilt to the right
56ctx.setLineWidth(lineThick)
57ctx.move(to: CGPoint(x: lx0, y: groupCY + gap - 8))
58ctx.addLine(to: CGPoint(x: lx1, y: groupCY + gap + 14))
59ctx.strokePath()
60
61// Line 2 (middle) — gentle curve
62ctx.setLineWidth(lineThick - 4)
63ctx.move(to: CGPoint(x: lx0, y: groupCY + 4))
64ctx.addQuadCurve(
65 to: CGPoint(x: lx1, y: groupCY - 6),
66 control: CGPoint(x: s / 2, y: groupCY - 30) // bows slightly down in screen
67)
68ctx.strokePath()
69
70// Line 3 (bottom) — slight tilt, slightly shorter
71let lineW3: CGFloat = lineW - 28
72let lx0b = (s - lineW3) / 2
73let lx1b = lx0b + lineW3
74ctx.setLineWidth(lineThick - 2)
75ctx.move(to: CGPoint(x: lx0b, y: groupCY - gap + 6))
76ctx.addLine(to: CGPoint(x: lx1b, y: groupCY - gap - 8))
77ctx.strokePath()
78
79// ---------------------------------------------------------------------------
80// Save
81// ---------------------------------------------------------------------------
82let img = ctx.makeImage()!
83let url = URL(fileURLWithPath: "SophaxChat/Assets.xcassets/AppIcon.appiconset/icon_1024.png",
84 relativeTo: URL(fileURLWithPath: FileManager.default.currentDirectoryPath))
85let dest = CGImageDestinationCreateWithURL(url as CFURL, "public.png" as CFString, 1, nil)!
86CGImageDestinationAddImage(dest, img, nil)
87CGImageDestinationFinalize(dest)
88print("✓ Icon saved to \(url.path)")