Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: CI

on:
push:
branches: [main, master]
pull_request:

jobs:
test-ios:
name: Test iOS
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- name: Test
run: |
xcodebuild \
-project XColor.xcodeproj \
-scheme "XColor iOS" \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 16' \
clean test

test-tvos:
name: Test tvOS
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- name: Test
run: |
xcodebuild \
-project XColor.xcodeproj \
-scheme "XColor tvOS" \
-destination 'platform=tvOS Simulator,name=Apple TV 4K (3rd generation)' \
clean test

test-macos:
name: Test macOS
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- name: Test
run: |
xcodebuild \
-project XColor.xcodeproj \
-scheme "XColor macOS" \
-destination 'platform=macOS,arch=arm64' \
clean test

test-spm:
name: Test SPM
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- name: Build and Test
run: swift test
28 changes: 28 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// swift-tools-version: 5.9
import PackageDescription

let package = Package(
name: "XColor",
platforms: [
.iOS(.v16),
.watchOS(.v9),
.tvOS(.v16),
.macOS(.v13),
.visionOS(.v1)
],
products: [
.library(name: "XColor", targets: ["XColor"])
],
targets: [
.target(
name: "XColor",
path: "Source",
exclude: ["Supporting Files"]
),
.testTarget(
name: "XColorTests",
dependencies: ["XColor"],
path: "XColorTests"
)
]
)
91 changes: 39 additions & 52 deletions Source/XColor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct Components {
let green: UInt8
let blue: UInt8
let alpha: Double

init(red: UInt8, green: UInt8, blue: UInt8, alpha: Double = 1) {
self.red = red
self.green = green
Expand All @@ -20,81 +20,68 @@ struct Components {
}
}

class XColor {
struct XColor {

private let color: UInt32
private var alpha: Double = 1
private let alpha: Double

init?(hexColor: String) {
guard let color = XColor.validatedColor(hexString: hexColor) else { return nil }
self.color = color
}

init?(hexColor: Int) {
self.color = UInt32(hexColor)
}

init?(hexColor: Int, alpha: Double) {
self.color = UInt32(hexColor)
self.alpha = alpha
self.alpha = 1.0
}

init?(hexColor: String, alpha: Double) {
guard let color = XColor.validatedColor(hexString: hexColor) else { return nil }
self.color = color
self.alpha = alpha
}


init?(hexColor: Int) {
guard let color = UInt32(exactly: hexColor) else { return nil }
self.color = color
self.alpha = 1.0
}

init?(hexColor: Int, alpha: Double) {
guard let color = UInt32(exactly: hexColor) else { return nil }
self.color = color
self.alpha = alpha
}

var components: Components? {
if (0x000 ... 0xFFF ~= color) {
let red = UInt8((color & 0xF00) >> 8)
let green = UInt8((color & 0x0F0) >> 4)
let blue = UInt8(color & 0x00F)
return Components(red: red, green: green, blue: blue, alpha: alpha)
} else if (0x000000 ... 0xFFFFFF ~= color) {
if 0x000 ... 0xFFF ~= color {
// 3-char shorthand: each nibble is doubled (e.g. #FA4 → #FFAA44)
let rn = UInt8((color & 0xF00) >> 8)
let gn = UInt8((color & 0x0F0) >> 4)
let bn = UInt8(color & 0x00F)
return Components(
red: (rn << 4) | rn,
green: (gn << 4) | gn,
blue: (bn << 4) | bn,
alpha: alpha
)
} else if 0x000000 ... 0xFFFFFF ~= color {
let red = UInt8((color & 0xFF0000) >> 16)
let green = UInt8((color & 0x00FF00) >> 8)
let blue = UInt8(color & 0x0000FF)
return Components(red: red, green: green, blue: blue, alpha: alpha)
} else if (0x00000000 ... 0xFFFFFFFF ~= color) {
} else {
// 8-char RGBA: last byte is implicit alpha
let red = UInt8((color & 0xFF000000) >> 24)
let green = UInt8((color & 0x00FF0000) >> 16)
let blue = UInt8((color & 0x0000FF00) >> 8)
let alpha = Double(UInt8(color & 0x000000FF)) / 255
return Components(red: red, green: green, blue: blue, alpha: alpha)
let implicitAlpha = Double(color & 0x000000FF) / 255
return Components(red: red, green: green, blue: blue, alpha: implicitAlpha)
}

return nil
}

private static func validatedColor(hexString: String) -> UInt32? {
guard let str = XColor.sanitizedHexString(hexString: hexString) else {
return nil
}

guard let color = UInt32(str, radix: 16) else {
return nil
}

return color
}

private static func sanitizedHexString(hexString: String) -> String? {

private static func validatedColor(hexString: String) -> UInt32? {
var str = hexString

if (str.hasPrefix("#")) {
if str.hasPrefix("#") {
str.remove(at: str.startIndex)
}

if (!valid(str)) {
return nil
}

return str
}

private static func valid(_ s: String) -> Bool {
return s.count == 3 || s.count == 6 || s.count == 8
guard str.count == 3 || str.count == 6 || str.count == 8 else { return nil }
return UInt32(str, radix: 16)
}
}
13 changes: 7 additions & 6 deletions XColor.podspec
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
Pod::Spec.new do |spec|
spec.name = "XColor"
spec.version = "0.3"
spec.version = "0.4"
spec.summary = "XColor is a color handling extension for UIColor written in Swift."
spec.homepage = "https://github.com/jaumevn/XColor"
spec.license = { :type => "MIT", :file => "LICENSE" }
spec.source = { :git => "https://github.com/jaumevn/XColor.git", :tag => "#{spec.version}" }
spec.author = { "Jaume Vinas Navas" => "jaumevn@icloud.com" }

spec.ios.deployment_target = '8.0'
spec.watchos.deployment_target = '2.0'
spec.tvos.deployment_target = '9.0'
spec.macos.deployment_target = '10.9'
spec.ios.deployment_target = '16.0'
spec.watchos.deployment_target = '9.0'
spec.tvos.deployment_target = '16.0'
spec.macos.deployment_target = '13.0'
spec.visionos.deployment_target = '1.0'

spec.swift_version = '5.0'
spec.swift_version = '5.9'

spec.source_files = 'Source/*.swift'
end
26 changes: 14 additions & 12 deletions XColor.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 13.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.jaumevn.XColor-macOS";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = macosx;
Expand All @@ -631,7 +631,7 @@
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 13.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.jaumevn.XColor-macOS";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = macosx;
Expand All @@ -653,7 +653,7 @@
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MACOSX_DEPLOYMENT_TARGET = 13.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.jaumevn.XColor-macOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
Expand All @@ -674,7 +674,7 @@
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MACOSX_DEPLOYMENT_TARGET = 13.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.jaumevn.XColor-macOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
Expand Down Expand Up @@ -818,7 +818,7 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "$(SRCROOT)/Source/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -848,7 +848,7 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "$(SRCROOT)/Source/Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -870,6 +870,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = XColorTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -889,6 +890,7 @@
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = XColorTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -926,7 +928,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
WATCHOS_DEPLOYMENT_TARGET = 9.0;
};
name = Debug;
};
Expand Down Expand Up @@ -955,7 +957,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 2.0;
WATCHOS_DEPLOYMENT_TARGET = 9.0;
};
name = Release;
};
Expand Down Expand Up @@ -983,7 +985,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.0;
TVOS_DEPLOYMENT_TARGET = 16.0;
};
name = Debug;
};
Expand Down Expand Up @@ -1011,7 +1013,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 9.0;
TVOS_DEPLOYMENT_TARGET = 16.0;
};
name = Release;
};
Expand All @@ -1032,7 +1034,7 @@
SDKROOT = appletvos;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 12.4;
TVOS_DEPLOYMENT_TARGET = 16.0;
};
name = Debug;
};
Expand All @@ -1053,7 +1055,7 @@
SDKROOT = appletvos;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 12.4;
TVOS_DEPLOYMENT_TARGET = 16.0;
};
name = Release;
};
Expand Down
Loading
Loading