diff --git a/apps/ios/Branding/README.md b/apps/ios/Branding/README.md new file mode 100644 index 0000000..740cd86 --- /dev/null +++ b/apps/ios/Branding/README.md @@ -0,0 +1,23 @@ +# Branding + +`logo.svg` is the source artwork: the Monero monogram in black and white — +two outer legs, a central V descending onto a full-width base bar, one uniform +stroke width (118 of 1024) so it stays legible at 60 px. + +iOS cannot use SVG for app icons, so the PNGs in +`Koins/Assets.xcassets/AppIcon.appiconset` are rendered from the same geometry: + +```sh +cd apps/ios +swift Branding/make-icons.swift Koins/Assets.xcassets/AppIcon.appiconset +``` + +That writes the 1024×1024 icon (black ground, white mark, no alpha channel — +the App Store rejects icons with alpha) plus `Branding/logo-light.png`, the +inverted variant. + +The asset catalog uses the single-size format, so Xcode derives every size the +device needs from the 1024. + +Note: the Monero name and mark are the Monero Project's; check their brand +guidance before shipping this publicly. diff --git a/apps/ios/Branding/logo-light.png b/apps/ios/Branding/logo-light.png new file mode 100644 index 0000000..c227282 Binary files /dev/null and b/apps/ios/Branding/logo-light.png differ diff --git a/apps/ios/Branding/logo.svg b/apps/ios/Branding/logo.svg new file mode 100644 index 0000000..120ccdf --- /dev/null +++ b/apps/ios/Branding/logo.svg @@ -0,0 +1,17 @@ + + Koins — Monero mark (monochrome) + + + + + + + + diff --git a/apps/ios/Branding/make-icons.swift b/apps/ios/Branding/make-icons.swift new file mode 100644 index 0000000..25be929 --- /dev/null +++ b/apps/ios/Branding/make-icons.swift @@ -0,0 +1,81 @@ +// Regenerates the app icon PNGs from the same geometry as Branding/logo.svg. +// +// cd apps/ios +// swift Branding/make-icons.swift Koins/Assets.xcassets/AppIcon.appiconset +// +// iOS cannot use SVG for app icons, so the SVG is the source artwork and this +// script produces the raster the asset catalog needs. It also writes +// Branding/logo-light.png (white ground, black mark). +import AppKit +import CoreGraphics +import Foundation + +// Draws the same geometry as Branding/logo.svg with CoreGraphics, because iOS +// app icons must be raster images. +func drawIcon(size: CGFloat, inverted: Bool = false) -> CGImage? { + let scale = size / 1024.0 + let colorSpace = CGColorSpaceCreateDeviceRGB() + guard let context = CGContext(data: nil, + width: Int(size), + height: Int(size), + bitsPerComponent: 8, + bytesPerRow: 0, + space: colorSpace, + bitmapInfo: CGImageAlphaInfo.noneSkipLast.rawValue) else { return nil } + + let background = inverted ? NSColor.white : NSColor.black + let foreground = inverted ? NSColor.black : NSColor.white + context.setFillColor(background.cgColor) + context.fill(CGRect(x: 0, y: 0, width: size, height: size)) + + context.setStrokeColor(foreground.cgColor) + context.setLineWidth(118 * scale) + context.setLineCap(.butt) + context.setLineJoin(.miter) + + func point(_ x: CGFloat, _ y: CGFloat) -> CGPoint { + // SVG y grows downwards, CoreGraphics grows upwards. + CGPoint(x: x * scale, y: size - y * scale) + } + + // Left leg continuing into the central V (one path, so the top corner is a + // clean miter rather than two overlapping strokes). + context.beginPath() + context.move(to: point(279, 758)) + context.addLine(to: point(279, 280)) + context.addLine(to: point(512, 640)) + context.strokePath() + + // Right leg, mirrored. + context.beginPath() + context.move(to: point(745, 758)) + context.addLine(to: point(745, 280)) + context.addLine(to: point(512, 640)) + context.strokePath() + + // Full-width bar across the base. + context.beginPath() + context.move(to: point(220, 699)) + context.addLine(to: point(804, 699)) + context.strokePath() + + return context.makeImage() +} + +func write(_ image: CGImage, to path: String) { + let rep = NSBitmapImageRep(cgImage: image) + guard let data = rep.representation(using: .png, properties: [:]) else { return } + try? data.write(to: URL(fileURLWithPath: path)) + print("wrote \(path)") +} + +let outputDir = CommandLine.arguments.count > 1 ? CommandLine.arguments[1] : "/tmp" +try? FileManager.default.createDirectory(atPath: outputDir, withIntermediateDirectories: true) + +if let icon = drawIcon(size: 1024) { + write(icon, to: "\(outputDir)/AppIcon-1024.png") +} +// A light variant, handy for other surfaces (white background, black mark). +if let light = drawIcon(size: 1024, inverted: true) { + write(light, to: "\(outputDir)/AppIcon-light-1024.png") +} diff --git a/apps/ios/Koins/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png b/apps/ios/Koins/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png new file mode 100644 index 0000000..0ce8d77 Binary files /dev/null and b/apps/ios/Koins/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png differ diff --git a/apps/ios/Koins/Assets.xcassets/AppIcon.appiconset/Contents.json b/apps/ios/Koins/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..f22e10c --- /dev/null +++ b/apps/ios/Koins/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "AppIcon-1024.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/ios/Koins/Assets.xcassets/Contents.json b/apps/ios/Koins/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/apps/ios/Koins/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/ios/project.yml b/apps/ios/project.yml index 5f5daca..7e68967 100644 --- a/apps/ios/project.yml +++ b/apps/ios/project.yml @@ -29,6 +29,7 @@ targets: CODE_SIGN_STYLE: Automatic DEVELOPMENT_TEAM: RX6767S6BW CODE_SIGNING_ALLOWED[sdk=iphonesimulator*]: NO + ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon SWIFT_OBJC_BRIDGING_HEADER: Koins/Bridge/Koins-Bridging-Header.h OTHER_LDFLAGS[sdk=iphoneos*]: - "$(inherited)"