Skip to content

Instantly share code, notes, and snippets.

@hyukhur
Created November 16, 2020 22:35
Show Gist options
  • Save hyukhur/fef974284bc14f16d59520d137d2a82c to your computer and use it in GitHub Desktop.
Save hyukhur/fef974284bc14f16d59520d137d2a82c to your computer and use it in GitHub Desktop.
//
// Color+Additions.swift
// EasyDrugs
//
// Created by Hyuk Hur on 2020-11-16.
//
import SwiftUI
extension Color {
init(hex: String, alpha: UInt64 = 255) {
let hexString = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
let scanner = Scanner(string: hexString)
if (hexString.hasPrefix("#")) {
scanner.currentIndex = hexString.index(hexString.startIndex, offsetBy: 1)
}
var color: UInt64 = 0
Scanner(string: hexString).scanHexInt64(&color)
let pattern: HexPattern
switch hexString.count {
case 3,4:
pattern = .rgb
case 6,7:
pattern = .rrggbb
case 8,9:
pattern = .aarrggbb
default:
pattern = .rrggbb
}
self.init(color, alpha: alpha, pattern: pattern)
}
enum HexPattern {
case rgb // RGB (12-bit) #RGB
case rrggbb // RGB (24-bit) #RRGGBB
case aarrggbb // ARGB (32-bit) #AARRGGBB
func colors(_ hex: UInt64, _ alpha: UInt64) -> (alpha: UInt64, red: UInt64, green: UInt64, blue: UInt64) {
switch self {
case .rgb:
return (alpha, (hex >> 8) * 17, (hex >> 4 & 0xF) * 17, (hex & 0xF) * 17)
case .rrggbb:
return (alpha, hex >> 16, hex >> 8 & 0xFF, hex & 0xFF)
case .aarrggbb:
return (hex >> 24, hex >> 16 & 0xFF, hex >> 8 & 0xFF, hex & 0xFF)
}
}
}
init(_ hex: UInt64, alpha: UInt64 = 255, pattern: HexPattern = .rrggbb) {
let (a, r, g, b) = pattern.colors(hex, alpha)
self.init( .sRGB,
red: Double(r) / 255,
green: Double(g) / 255,
blue: Double(b) / 255,
opacity: Double(a) / 255
)
}
/*
init(_ hex: UInt64) {
let pattern: HexPattern
switch hex{
case 0x000...0xFFF:
pattern = .rgb
case 0x000000...0xFFFFFF:
pattern = .rrggbb
case 0x00000000...0xFFFFFFFF:
pattern = .aarrggbb
default:
pattern = .rrggbb
}
self.init(hex, pattern: pattern)
}
*/
}
//
// ColorTests.swift
// EasyDrugsTests
//
// Created by Hank Hur on 2020-11-16.
//
import XCTest
import SwiftUI
import CoreGraphics
class ColorTests: XCTestCase {
func test12BitHex() throws {
let pattern = Color.HexPattern.rgb
XCTAssertEqual(Color(0xFFF, pattern: pattern).cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.9999999403953552, accuracy: 0.00000001)
XCTAssertEqual(Color(0, pattern: pattern).cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(0x8FF, pattern: pattern).cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(0xF8F, pattern: pattern).cgColor?.components?[1] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFF8, pattern: pattern).cgColor?.components?[2] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFF8, pattern: pattern).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 1, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFF8, alpha: 0, pattern: pattern).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFF8, alpha: 0x8, pattern: pattern).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0.0313725508749485, accuracy: 0.00000001)
}
func test24BitHex() {
let pattern = Color.HexPattern.rrggbb
XCTAssertEqual(Color(0xFFFFFF, pattern: pattern).cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.9999999403953552, accuracy: 0.00000001)
XCTAssertEqual(Color(0, pattern: pattern).cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(0x88FFFF, pattern: pattern).cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFF88FF, pattern: pattern).cgColor?.components?[1] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFFFF88, pattern: pattern).cgColor?.components?[2] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFFFF88, pattern: pattern).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 1, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFFFF88, alpha: 0, pattern: pattern).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFFFF88, alpha: 0x8, pattern: pattern).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0.0313725508749485, accuracy: 0.00000001)
}
func test32BitHex() {
let pattern = Color.HexPattern.aarrggbb
XCTAssertEqual(Color(0xFFFFFFFF, pattern: pattern).cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.9999999403953552, accuracy: 0.00000001)
XCTAssertEqual(Color(0, pattern: pattern).cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFF88FFFF, pattern: pattern).cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFFFF88FF, pattern: pattern).cgColor?.components?[1] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFFFFFF88, pattern: pattern).cgColor?.components?[2] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(0xFFFFFF88, alpha: 0, pattern: pattern).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 1, accuracy: 0.00000001)
XCTAssertEqual(Color(0x00FFFF88, alpha: 1, pattern: pattern).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(0x88FFFF88, alpha: 0, pattern: pattern).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
}
func test12BitHexString() throws {
XCTAssertEqual(Color(hex: "FFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.9999999403953552, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "000").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "8FF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "F8F").cgColor?.components?[1] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FF8").cgColor?.components?[2] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FF8").cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 1, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FF8", alpha: 0).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FF8", alpha: 0x8).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0.0313725508749485, accuracy: 0.00000001)
}
func test24BitHexString() {
XCTAssertEqual(Color(hex: "FFFFFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.9999999403953552, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "000000").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "88FFFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FF88FF").cgColor?.components?[1] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FFFF88").cgColor?.components?[2] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FFFF88").cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 1, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FFFF88", alpha: 0).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FFFF88", alpha: 0x8).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0.0313725508749485, accuracy: 0.00000001)
}
func test32BitHexString() {
XCTAssertEqual(Color(hex: "FFFFFFFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.9999999403953552, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "00000000").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FF88FFFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FFFF88FF").cgColor?.components?[1] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FFFFFF88").cgColor?.components?[2] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "FFFFFF88", alpha: 0).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 1, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "00FFFF88", alpha: 1).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "88FFFF88", alpha: 0).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
}
func test12BitHexHashString() throws {
XCTAssertEqual(Color(hex: "#FFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.9999999403953552, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#000").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#8FF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#F8F").cgColor?.components?[1] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FF8").cgColor?.components?[2] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FF8").cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 1, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FF8", alpha: 0).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FF8", alpha: 0x8).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0.0313725508749485, accuracy: 0.00000001)
}
func test24BitHexHashString() {
XCTAssertEqual(Color(hex: "#FFFFFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.9999999403953552, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#000000").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#88FFFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FF88FF").cgColor?.components?[1] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FFFF88").cgColor?.components?[2] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FFFF88").cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 1, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FFFF88", alpha: 0).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FFFF88", alpha: 0x8).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0.0313725508749485, accuracy: 0.00000001)
}
func test32BitHexHashString() {
XCTAssertEqual(Color(hex: "#FFFFFFFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.9999999403953552, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#00000000").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FF88FFFF").cgColor?.components?[0] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FFFF88FF").cgColor?.components?[1] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FFFFFF88").cgColor?.components?[2] ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#FFFFFF88", alpha: 0).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 1, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#00FFFF88", alpha: 1).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0, accuracy: 0.00000001)
XCTAssertEqual(Color(hex: "#88FFFF88", alpha: 0).cgColor?.alpha ?? CGFloat.greatestFiniteMagnitude, 0.5333333611488342, accuracy: 0.00000001)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment