├── .gitignore ├── CostumeKit.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── CostumeKit.xcscheme ├── CostumeKit ├── Color.swift ├── ColorConvertible.swift ├── ColorPalette.swift ├── Costume.swift ├── CostumeKit.h ├── Font.swift ├── FontConvertible.swift ├── Info.plist ├── SVG.swift └── SystemFont.swift ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /CostumeKit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 30E1A6A51D9CEA9B00E63D0E /* CostumeKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E1A6A31D9CEA9B00E63D0E /* CostumeKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 30E1A6B41D9CEAC200E63D0E /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E1A6AC1D9CEAC200E63D0E /* Color.swift */; }; 12 | 30E1A6B51D9CEAC200E63D0E /* ColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E1A6AD1D9CEAC200E63D0E /* ColorPalette.swift */; }; 13 | 30E1A6B61D9CEAC200E63D0E /* Costume.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E1A6AE1D9CEAC200E63D0E /* Costume.swift */; }; 14 | 30E1A6B81D9CEAC200E63D0E /* Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E1A6B01D9CEAC200E63D0E /* Font.swift */; }; 15 | 30E1A6B91D9CEAC200E63D0E /* SVG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E1A6B11D9CEAC200E63D0E /* SVG.swift */; }; 16 | 30E1A6BB1D9CEAC200E63D0E /* SystemFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E1A6B31D9CEAC200E63D0E /* SystemFont.swift */; }; 17 | 30E1A6BD1D9CEB8D00E63D0E /* FontConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E1A6BC1D9CEB8D00E63D0E /* FontConvertible.swift */; }; 18 | 30E1A6BF1D9CEBB100E63D0E /* ColorConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E1A6BE1D9CEBB100E63D0E /* ColorConvertible.swift */; }; 19 | 30E1A6C31D9CF1E300E63D0E /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 30E1A6C21D9CF1E300E63D0E /* README.md */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 30E1A6A01D9CEA9B00E63D0E /* CostumeKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CostumeKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 30E1A6A31D9CEA9B00E63D0E /* CostumeKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CostumeKit.h; sourceTree = ""; }; 25 | 30E1A6A41D9CEA9B00E63D0E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 26 | 30E1A6AC1D9CEAC200E63D0E /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; 27 | 30E1A6AD1D9CEAC200E63D0E /* ColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorPalette.swift; sourceTree = ""; }; 28 | 30E1A6AE1D9CEAC200E63D0E /* Costume.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Costume.swift; sourceTree = ""; }; 29 | 30E1A6B01D9CEAC200E63D0E /* Font.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Font.swift; sourceTree = ""; }; 30 | 30E1A6B11D9CEAC200E63D0E /* SVG.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SVG.swift; sourceTree = ""; }; 31 | 30E1A6B31D9CEAC200E63D0E /* SystemFont.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemFont.swift; sourceTree = ""; }; 32 | 30E1A6BC1D9CEB8D00E63D0E /* FontConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FontConvertible.swift; sourceTree = ""; }; 33 | 30E1A6BE1D9CEBB100E63D0E /* ColorConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorConvertible.swift; sourceTree = ""; }; 34 | 30E1A6C21D9CF1E300E63D0E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 30E1A69C1D9CEA9B00E63D0E /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | 30E1A6961D9CEA9B00E63D0E = { 49 | isa = PBXGroup; 50 | children = ( 51 | 30E1A6A21D9CEA9B00E63D0E /* CostumeKit */, 52 | 30E1A6A11D9CEA9B00E63D0E /* Products */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | 30E1A6A11D9CEA9B00E63D0E /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 30E1A6A01D9CEA9B00E63D0E /* CostumeKit.framework */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 30E1A6A21D9CEA9B00E63D0E /* CostumeKit */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 30E1A6AB1D9CEAAC00E63D0E /* infrastructure */, 68 | 30E1A6AC1D9CEAC200E63D0E /* Color.swift */, 69 | 30E1A6BE1D9CEBB100E63D0E /* ColorConvertible.swift */, 70 | 30E1A6AD1D9CEAC200E63D0E /* ColorPalette.swift */, 71 | 30E1A6AE1D9CEAC200E63D0E /* Costume.swift */, 72 | 30E1A6B01D9CEAC200E63D0E /* Font.swift */, 73 | 30E1A6BC1D9CEB8D00E63D0E /* FontConvertible.swift */, 74 | 30E1A6B11D9CEAC200E63D0E /* SVG.swift */, 75 | 30E1A6B31D9CEAC200E63D0E /* SystemFont.swift */, 76 | ); 77 | path = CostumeKit; 78 | sourceTree = ""; 79 | }; 80 | 30E1A6AB1D9CEAAC00E63D0E /* infrastructure */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 30E1A6C21D9CF1E300E63D0E /* README.md */, 84 | 30E1A6A31D9CEA9B00E63D0E /* CostumeKit.h */, 85 | 30E1A6A41D9CEA9B00E63D0E /* Info.plist */, 86 | ); 87 | name = infrastructure; 88 | sourceTree = ""; 89 | }; 90 | /* End PBXGroup section */ 91 | 92 | /* Begin PBXHeadersBuildPhase section */ 93 | 30E1A69D1D9CEA9B00E63D0E /* Headers */ = { 94 | isa = PBXHeadersBuildPhase; 95 | buildActionMask = 2147483647; 96 | files = ( 97 | 30E1A6A51D9CEA9B00E63D0E /* CostumeKit.h in Headers */, 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | /* End PBXHeadersBuildPhase section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | 30E1A69F1D9CEA9B00E63D0E /* CostumeKit */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = 30E1A6A81D9CEA9B00E63D0E /* Build configuration list for PBXNativeTarget "CostumeKit" */; 107 | buildPhases = ( 108 | 30E1A69B1D9CEA9B00E63D0E /* Sources */, 109 | 30E1A69C1D9CEA9B00E63D0E /* Frameworks */, 110 | 30E1A69D1D9CEA9B00E63D0E /* Headers */, 111 | 30E1A69E1D9CEA9B00E63D0E /* Resources */, 112 | ); 113 | buildRules = ( 114 | ); 115 | dependencies = ( 116 | ); 117 | name = CostumeKit; 118 | productName = CostumeKit; 119 | productReference = 30E1A6A01D9CEA9B00E63D0E /* CostumeKit.framework */; 120 | productType = "com.apple.product-type.framework"; 121 | }; 122 | /* End PBXNativeTarget section */ 123 | 124 | /* Begin PBXProject section */ 125 | 30E1A6971D9CEA9B00E63D0E /* Project object */ = { 126 | isa = PBXProject; 127 | attributes = { 128 | LastUpgradeCheck = 0800; 129 | ORGANIZATIONNAME = "Jake Marsh"; 130 | TargetAttributes = { 131 | 30E1A69F1D9CEA9B00E63D0E = { 132 | CreatedOnToolsVersion = 8.0; 133 | DevelopmentTeam = WAPMUZDLZP; 134 | LastSwiftMigration = 0800; 135 | ProvisioningStyle = Automatic; 136 | }; 137 | }; 138 | }; 139 | buildConfigurationList = 30E1A69A1D9CEA9B00E63D0E /* Build configuration list for PBXProject "CostumeKit" */; 140 | compatibilityVersion = "Xcode 3.2"; 141 | developmentRegion = English; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | ); 146 | mainGroup = 30E1A6961D9CEA9B00E63D0E; 147 | productRefGroup = 30E1A6A11D9CEA9B00E63D0E /* Products */; 148 | projectDirPath = ""; 149 | projectRoot = ""; 150 | targets = ( 151 | 30E1A69F1D9CEA9B00E63D0E /* CostumeKit */, 152 | ); 153 | }; 154 | /* End PBXProject section */ 155 | 156 | /* Begin PBXResourcesBuildPhase section */ 157 | 30E1A69E1D9CEA9B00E63D0E /* Resources */ = { 158 | isa = PBXResourcesBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | /* End PBXResourcesBuildPhase section */ 165 | 166 | /* Begin PBXSourcesBuildPhase section */ 167 | 30E1A69B1D9CEA9B00E63D0E /* Sources */ = { 168 | isa = PBXSourcesBuildPhase; 169 | buildActionMask = 2147483647; 170 | files = ( 171 | 30E1A6B91D9CEAC200E63D0E /* SVG.swift in Sources */, 172 | 30E1A6B41D9CEAC200E63D0E /* Color.swift in Sources */, 173 | 30E1A6BF1D9CEBB100E63D0E /* ColorConvertible.swift in Sources */, 174 | 30E1A6B61D9CEAC200E63D0E /* Costume.swift in Sources */, 175 | 30E1A6B81D9CEAC200E63D0E /* Font.swift in Sources */, 176 | 30E1A6BD1D9CEB8D00E63D0E /* FontConvertible.swift in Sources */, 177 | 30E1A6C31D9CF1E300E63D0E /* README.md in Sources */, 178 | 30E1A6B51D9CEAC200E63D0E /* ColorPalette.swift in Sources */, 179 | 30E1A6BB1D9CEAC200E63D0E /* SystemFont.swift in Sources */, 180 | ); 181 | runOnlyForDeploymentPostprocessing = 0; 182 | }; 183 | /* End PBXSourcesBuildPhase section */ 184 | 185 | /* Begin XCBuildConfiguration section */ 186 | 30E1A6A61D9CEA9B00E63D0E /* Debug */ = { 187 | isa = XCBuildConfiguration; 188 | buildSettings = { 189 | ALWAYS_SEARCH_USER_PATHS = NO; 190 | CLANG_ANALYZER_NONNULL = YES; 191 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 192 | CLANG_CXX_LIBRARY = "libc++"; 193 | CLANG_ENABLE_MODULES = YES; 194 | CLANG_ENABLE_OBJC_ARC = YES; 195 | CLANG_WARN_BOOL_CONVERSION = YES; 196 | CLANG_WARN_CONSTANT_CONVERSION = YES; 197 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 198 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 199 | CLANG_WARN_EMPTY_BODY = YES; 200 | CLANG_WARN_ENUM_CONVERSION = YES; 201 | CLANG_WARN_INFINITE_RECURSION = YES; 202 | CLANG_WARN_INT_CONVERSION = YES; 203 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 204 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 205 | CLANG_WARN_UNREACHABLE_CODE = YES; 206 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 207 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 208 | COPY_PHASE_STRIP = NO; 209 | CURRENT_PROJECT_VERSION = 1; 210 | DEBUG_INFORMATION_FORMAT = dwarf; 211 | ENABLE_STRICT_OBJC_MSGSEND = YES; 212 | ENABLE_TESTABILITY = YES; 213 | GCC_C_LANGUAGE_STANDARD = gnu99; 214 | GCC_DYNAMIC_NO_PIC = NO; 215 | GCC_NO_COMMON_BLOCKS = YES; 216 | GCC_OPTIMIZATION_LEVEL = 0; 217 | GCC_PREPROCESSOR_DEFINITIONS = ( 218 | "DEBUG=1", 219 | "$(inherited)", 220 | ); 221 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 222 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 223 | GCC_WARN_UNDECLARED_SELECTOR = YES; 224 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 225 | GCC_WARN_UNUSED_FUNCTION = YES; 226 | GCC_WARN_UNUSED_VARIABLE = YES; 227 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 228 | MTL_ENABLE_DEBUG_INFO = YES; 229 | ONLY_ACTIVE_ARCH = YES; 230 | SDKROOT = iphoneos; 231 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 232 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 233 | TARGETED_DEVICE_FAMILY = "1,2"; 234 | VERSIONING_SYSTEM = "apple-generic"; 235 | VERSION_INFO_PREFIX = ""; 236 | }; 237 | name = Debug; 238 | }; 239 | 30E1A6A71D9CEA9B00E63D0E /* Release */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | ALWAYS_SEARCH_USER_PATHS = NO; 243 | CLANG_ANALYZER_NONNULL = YES; 244 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 245 | CLANG_CXX_LIBRARY = "libc++"; 246 | CLANG_ENABLE_MODULES = YES; 247 | CLANG_ENABLE_OBJC_ARC = YES; 248 | CLANG_WARN_BOOL_CONVERSION = YES; 249 | CLANG_WARN_CONSTANT_CONVERSION = YES; 250 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 251 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 252 | CLANG_WARN_EMPTY_BODY = YES; 253 | CLANG_WARN_ENUM_CONVERSION = YES; 254 | CLANG_WARN_INFINITE_RECURSION = YES; 255 | CLANG_WARN_INT_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 258 | CLANG_WARN_UNREACHABLE_CODE = YES; 259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 260 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 261 | COPY_PHASE_STRIP = NO; 262 | CURRENT_PROJECT_VERSION = 1; 263 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 264 | ENABLE_NS_ASSERTIONS = NO; 265 | ENABLE_STRICT_OBJC_MSGSEND = YES; 266 | GCC_C_LANGUAGE_STANDARD = gnu99; 267 | GCC_NO_COMMON_BLOCKS = YES; 268 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 269 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 270 | GCC_WARN_UNDECLARED_SELECTOR = YES; 271 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 272 | GCC_WARN_UNUSED_FUNCTION = YES; 273 | GCC_WARN_UNUSED_VARIABLE = YES; 274 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 275 | MTL_ENABLE_DEBUG_INFO = NO; 276 | SDKROOT = iphoneos; 277 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 278 | TARGETED_DEVICE_FAMILY = "1,2"; 279 | VALIDATE_PRODUCT = YES; 280 | VERSIONING_SYSTEM = "apple-generic"; 281 | VERSION_INFO_PREFIX = ""; 282 | }; 283 | name = Release; 284 | }; 285 | 30E1A6A91D9CEA9B00E63D0E /* Debug */ = { 286 | isa = XCBuildConfiguration; 287 | buildSettings = { 288 | CLANG_ENABLE_MODULES = YES; 289 | CODE_SIGN_IDENTITY = ""; 290 | DEFINES_MODULE = YES; 291 | DEVELOPMENT_TEAM = WAPMUZDLZP; 292 | DYLIB_COMPATIBILITY_VERSION = 1; 293 | DYLIB_CURRENT_VERSION = 1; 294 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 295 | INFOPLIST_FILE = CostumeKit/Info.plist; 296 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 297 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 298 | PRODUCT_BUNDLE_IDENTIFIER = com.jakemarsh.CostumeKit; 299 | PRODUCT_NAME = "$(TARGET_NAME)"; 300 | SKIP_INSTALL = YES; 301 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 302 | SWIFT_VERSION = 3.0; 303 | }; 304 | name = Debug; 305 | }; 306 | 30E1A6AA1D9CEA9B00E63D0E /* Release */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | CLANG_ENABLE_MODULES = YES; 310 | CODE_SIGN_IDENTITY = ""; 311 | DEFINES_MODULE = YES; 312 | DEVELOPMENT_TEAM = WAPMUZDLZP; 313 | DYLIB_COMPATIBILITY_VERSION = 1; 314 | DYLIB_CURRENT_VERSION = 1; 315 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 316 | INFOPLIST_FILE = CostumeKit/Info.plist; 317 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 318 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 319 | PRODUCT_BUNDLE_IDENTIFIER = com.jakemarsh.CostumeKit; 320 | PRODUCT_NAME = "$(TARGET_NAME)"; 321 | SKIP_INSTALL = YES; 322 | SWIFT_VERSION = 3.0; 323 | }; 324 | name = Release; 325 | }; 326 | /* End XCBuildConfiguration section */ 327 | 328 | /* Begin XCConfigurationList section */ 329 | 30E1A69A1D9CEA9B00E63D0E /* Build configuration list for PBXProject "CostumeKit" */ = { 330 | isa = XCConfigurationList; 331 | buildConfigurations = ( 332 | 30E1A6A61D9CEA9B00E63D0E /* Debug */, 333 | 30E1A6A71D9CEA9B00E63D0E /* Release */, 334 | ); 335 | defaultConfigurationIsVisible = 0; 336 | defaultConfigurationName = Release; 337 | }; 338 | 30E1A6A81D9CEA9B00E63D0E /* Build configuration list for PBXNativeTarget "CostumeKit" */ = { 339 | isa = XCConfigurationList; 340 | buildConfigurations = ( 341 | 30E1A6A91D9CEA9B00E63D0E /* Debug */, 342 | 30E1A6AA1D9CEA9B00E63D0E /* Release */, 343 | ); 344 | defaultConfigurationIsVisible = 0; 345 | }; 346 | /* End XCConfigurationList section */ 347 | }; 348 | rootObject = 30E1A6971D9CEA9B00E63D0E /* Project object */; 349 | } 350 | -------------------------------------------------------------------------------- /CostumeKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CostumeKit.xcodeproj/xcshareddata/xcschemes/CostumeKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /CostumeKit/Color.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Color.swift 3 | // CostumeKit 4 | // 5 | // Created by Jake Marsh on 8/7/16. 6 | // Copyright © 2016 Jake Marsh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public typealias Color = String 12 | 13 | extension Color : ColorConvertible { 14 | public var colorValue: UIColor { 15 | return UIColor(hexString: self)! 16 | } 17 | 18 | public static let none = UIColor.clear 19 | public static let white = UIColor.white 20 | public static let black = UIColor.black 21 | } 22 | 23 | // SwiftHEXColors.swift 24 | // 25 | // Copyright (c) 2014 Doan Truong Thi 26 | // 27 | // Permission is hereby granted, free of charge, to any person obtaining a copy 28 | // of this software and associated documentation files (the "Software"), to deal 29 | // in the Software without restriction, including without limitation the rights 30 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 31 | // copies of the Software, and to permit persons to whom the Software is 32 | // furnished to do so, subject to the following conditions: 33 | // 34 | // The above copyright notice and this permission notice shall be included in 35 | // all copies or substantial portions of the Software. 36 | // 37 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 39 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 43 | // THE SOFTWARE. 44 | 45 | #if os(iOS) || os(tvOS) 46 | import UIKit 47 | typealias SWColor = UIColor 48 | #else 49 | import Cocoa 50 | typealias SWColor = NSColor 51 | #endif 52 | 53 | private extension Int { 54 | func duplicate4bits() -> Int { 55 | return (self << 4) + self 56 | } 57 | } 58 | 59 | /// An extension of UIColor (on iOS) or NSColor (on OSX) providing HEX color handling. 60 | public extension SWColor { 61 | /** 62 | Create non-autoreleased color with in the given hex string. Alpha will be set as 1 by default. 63 | 64 | - parameter hexString: The hex string, with or without the hash character. 65 | - returns: A color with the given hex string. 66 | */ 67 | public convenience init?(hexString: String) { 68 | self.init(hexString: hexString, alpha: 1.0) 69 | } 70 | 71 | private convenience init?(hex3: Int, alpha: Float) { 72 | self.init(red: CGFloat( ((hex3 & 0xF00) >> 8).duplicate4bits() ) / 255.0, 73 | green: CGFloat( ((hex3 & 0x0F0) >> 4).duplicate4bits() ) / 255.0, 74 | blue: CGFloat( ((hex3 & 0x00F) >> 0).duplicate4bits() ) / 255.0, alpha: CGFloat(alpha)) 75 | } 76 | 77 | private convenience init?(hex6: Int, alpha: Float) { 78 | self.init(red: CGFloat( (hex6 & 0xFF0000) >> 16 ) / 255.0, 79 | green: CGFloat( (hex6 & 0x00FF00) >> 8 ) / 255.0, 80 | blue: CGFloat( (hex6 & 0x0000FF) >> 0 ) / 255.0, alpha: CGFloat(alpha)) 81 | } 82 | 83 | /** 84 | Create non-autoreleased color with in the given hex string and alpha. 85 | 86 | - parameter hexString: The hex string, with or without the hash character. 87 | - parameter alpha: The alpha value, a floating value between 0 and 1. 88 | - returns: A color with the given hex string and alpha. 89 | */ 90 | public convenience init?(hexString: String, alpha: Float) { 91 | var hex = hexString 92 | 93 | // Check for hash and remove the hash 94 | if hex.hasPrefix("#") { 95 | hex = hex.substring(from: hex.index(hex.startIndex, offsetBy: 1)) 96 | } 97 | 98 | guard let hexVal = Int(hex, radix: 16) else { 99 | self.init() 100 | return nil 101 | } 102 | 103 | switch hex.characters.count { 104 | case 3: 105 | self.init(hex3: hexVal, alpha: alpha) 106 | case 6: 107 | self.init(hex6: hexVal, alpha: alpha) 108 | default: 109 | // Note: 110 | // The swift 1.1 compiler is currently unable to destroy partially initialized classes in all cases, 111 | // so it disallows formation of a situation where it would have to. We consider this a bug to be fixed 112 | // in future releases, not a feature. -- Apple Forum 113 | self.init() 114 | return nil 115 | } 116 | } 117 | 118 | /** 119 | Create non-autoreleased color with in the given hex value. Alpha will be set as 1 by default. 120 | 121 | - parameter hex: The hex value. For example: 0xff8942 (no quotation). 122 | - returns: A color with the given hex value 123 | */ 124 | public convenience init?(hex: Int) { 125 | self.init(hex: hex, alpha: 1.0) 126 | } 127 | 128 | /** 129 | Create non-autoreleased color with in the given hex value and alpha 130 | 131 | - parameter hex: The hex value. For example: 0xff8942 (no quotation). 132 | - parameter alpha: The alpha value, a floating value between 0 and 1. 133 | - returns: color with the given hex value and alpha 134 | */ 135 | public convenience init?(hex: Int, alpha: Float) { 136 | if (0x000000 ... 0xFFFFFF) ~= hex { 137 | self.init(hex6: hex , alpha: alpha) 138 | } else { 139 | self.init() 140 | return nil 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /CostumeKit/ColorConvertible.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorConvertible.swift 3 | // CostumeKit 4 | // 5 | // Created by Jake Marsh on 9/28/16. 6 | // Copyright © 2016 Jake Marsh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | #if os(iOS) 12 | public typealias ColorType = UIColor 13 | #elseif os(macOS) 14 | public typealias ColorType = NSColor 15 | #endif 16 | 17 | public protocol ColorConvertible { 18 | var colorValue: ColorType { get } 19 | } 20 | 21 | extension ColorConvertible { 22 | public func darkened(amount: Float = 0.4) -> ColorType { 23 | return self.colorValue // TODO: Darken 24 | } 25 | } 26 | 27 | extension ColorType : ColorConvertible { 28 | public var colorValue: ColorType { return self } 29 | } 30 | -------------------------------------------------------------------------------- /CostumeKit/ColorPalette.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorPalette.swift 3 | // CostumeKit 4 | // 5 | // Created by Jake Marsh on 8/7/16. 6 | // Copyright © 2016 Jake Marsh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol ColorPalette : ColorConvertible { 12 | var rawValue: String { get } 13 | } 14 | 15 | public extension ColorPalette { 16 | var colorValue: UIColor { return rawValue.colorValue } 17 | } 18 | -------------------------------------------------------------------------------- /CostumeKit/Costume.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Costume.swift 3 | // CostumeKit 4 | // 5 | // Created by Jake Marsh on 8/7/16. 6 | // Copyright © 2016 Jake Marsh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Costume { 12 | var name: String { get } 13 | var description: String { get } 14 | } 15 | -------------------------------------------------------------------------------- /CostumeKit/CostumeKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // CostumeKit.h 3 | // CostumeKit 4 | // 5 | // Created by Jake Marsh on 9/28/16. 6 | // Copyright © 2016 Jake Marsh. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for CostumeKit. 12 | FOUNDATION_EXPORT double CostumeKitVersionNumber; 13 | 14 | //! Project version string for CostumeKit. 15 | FOUNDATION_EXPORT const unsigned char CostumeKitVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /CostumeKit/Font.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Font.swift 3 | // CostumeKit 4 | // 5 | // Created by Jake Marsh on 8/7/16. 6 | // Copyright © 2016 Jake Marsh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Font : FontConvertible { 12 | var size: FontSize { get set } 13 | } 14 | 15 | public enum FontSize { 16 | case textStyle(_: UIFontTextStyle) 17 | case fixed(_: CGFloat) 18 | } 19 | 20 | extension Font { 21 | public var pointSize: CGFloat { 22 | var pointSize: CGFloat 23 | 24 | switch size { 25 | case .textStyle(let style): pointSize = UIFont.preferredFont(forTextStyle: style).pointSize 26 | case .fixed(let ps): pointSize = ps + CGFloat(fixedSizeModifier) 27 | } 28 | 29 | return pointSize 30 | } 31 | 32 | var fixedSizeModifier: Int { 33 | let contentSize = UIApplication.shared.preferredContentSizeCategory 34 | 35 | switch contentSize { 36 | case UIContentSizeCategory.accessibilityExtraExtraExtraLarge: return 9 37 | case UIContentSizeCategory.accessibilityExtraExtraLarge: return 8 38 | case UIContentSizeCategory.accessibilityExtraLarge: return 7 39 | case UIContentSizeCategory.accessibilityLarge: return 6 40 | case UIContentSizeCategory.accessibilityMedium: return 5 41 | case UIContentSizeCategory.extraExtraExtraLarge: return 4 42 | case UIContentSizeCategory.extraExtraLarge: return 3 43 | case UIContentSizeCategory.extraLarge: return 2 44 | case UIContentSizeCategory.large: return 1 45 | case UIContentSizeCategory.medium: return 0 46 | case UIContentSizeCategory.small: return -1 47 | case UIContentSizeCategory.extraSmall: return -2 48 | default: return 0 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /CostumeKit/FontConvertible.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FontConvertible.swift 3 | // CostumeKit 4 | // 5 | // Created by Jake Marsh on 9/28/16. 6 | // Copyright © 2016 Jake Marsh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | #if os(iOS) 12 | public typealias FontType = UIFont 13 | #elseif os(macOS) 14 | public typealias FontType = NSFont 15 | #endif 16 | 17 | public protocol FontConvertible { 18 | var fontValue: UIFont { get } 19 | } 20 | 21 | extension FontType : FontConvertible { 22 | public var fontValue: FontType { return self } 23 | } 24 | -------------------------------------------------------------------------------- /CostumeKit/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /CostumeKit/SVG.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SVG.swift 3 | // CostumeKit 4 | // 5 | // Created by Jake Marsh on 8/7/16. 6 | // Copyright © 2016 Jake Marsh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol SVG { 12 | func metadata() -> SVGMetadata 13 | } 14 | 15 | public struct SVGMetadata { 16 | public let name: String 17 | public let size: CGSize 18 | public let fullColor: Bool 19 | 20 | public init(name: String, size: CGSize, fullColor: Bool = true) { 21 | self.name = name 22 | self.size = size 23 | self.fullColor = fullColor 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CostumeKit/SystemFont.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SystemFont.swift 3 | // CostumeKit 4 | // 5 | // Created by Jake Marsh on 8/17/16. 6 | // Copyright © 2016 Jake Marsh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct SystemFont : Font { 12 | public var weight: CGFloat = UIFontWeightRegular 13 | 14 | public init(size: FontSize = .textStyle(.body), weight: CGFloat = UIFontWeightRegular) { 15 | self.size = size 16 | self.weight = weight 17 | } 18 | 19 | // Font 20 | 21 | public var size: FontSize 22 | 23 | // FontConvertible 24 | 25 | public var fontValue: UIFont { 26 | return .systemFont(ofSize: pointSize, weight: weight) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Jake Marsh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | SwiftHEXColors.swift 24 | 25 | Copyright (c) 2014 Doan Truong Thi 26 | 27 | Permission is hereby granted, free of charge, to any person obtaining a copy 28 | of this software and associated documentation files (the "Software"), to deal 29 | in the Software without restriction, including without limitation the rights 30 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 31 | copies of the Software, and to permit persons to whom the Software is 32 | furnished to do so, subject to the following conditions: 33 | 34 | The above copyright notice and this permission notice shall be included in 35 | all copies or substantial portions of the Software. 36 | 37 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 39 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 43 | THE SOFTWARE. 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CostumeKit :tophat: 2 | 3 | > Base types for theming an app. 4 | 5 | **CostumeKit** is made of up a set of Swift protocols. They are meant to be implemented by you in your app. 6 | 7 | Featured in [_Little Bites of Cocoa Bite #270: Implementing Theming with CostumeKit_](https://littlebitesofcocoa.com/270-implementing-theming-with-costumekit) 8 | 9 | ## Color :art: 10 | 11 | Includes `Color` and `ColorPalette` protocols. 12 | 13 | Usage: 14 | 15 | ``` swift 16 | public enum MyAppColors : Color, ColorPalette { 17 | case white = "FFFFFF" 18 | case lightTeal = "3CB39E" 19 | case forestGreen = "216055" 20 | case black = "000000" 21 | } 22 | ``` 23 | 24 | ## Font :capital_abcd: 25 | 26 | Includes `Font` protocol, and one concrete `SystemFont` implementation for **iOS** system fonts. 27 | 28 | Usage: 29 | 30 | ``` swift 31 | public struct MyAppFont : Font { 32 | public init(size: FontSize = .textStyle(.body)) { 33 | self.size = size 34 | } 35 | 36 | // Font 37 | 38 | public var size: FontSize 39 | 40 | // FontConvertible 41 | 42 | public var FontValue: UIFont { 43 | return UIFont(name: "SomeCustomFont", size: pointSize)! 44 | } 45 | } 46 | ``` 47 | 48 | ## SVG :stars: 49 | 50 | Includes `SVG` Protocol and `SVGMetadata` type. 51 | 52 | Usage: 53 | 54 | ``` swift 55 | enum MyAppSVGs { 56 | case clockGlyph 57 | case bird 58 | } 59 | 60 | extension MyAppSVGs : SVG { 61 | public func metadata() -> SVGMetadata { 62 | switch self { 63 | case .clockGlyph: return SVGMetadata(name: "clock", size: CGSize(width: 100, height: 100), fullColor: false) 64 | case .bird: return SVGMetadata(name: "bird", size: CGSize(width: 58, height: 28), fullColor: true) 65 | } 66 | } 67 | } 68 | ``` 69 | 70 | What you do with `SVGMetadata` is up to you. I recommend [SwiftSVG](https://github.com/mchoe/SwiftSVG) from [Michael Choe](https://github.com/mchoe). [Read more here to learn how to use it](https://www.littlebitesofcocoa.com/198-parsing-rendering-svgs-with-swiftsvg). 71 | 72 | **CostumeKit**'s goals are to be a generic solution, so no assumptions are made about how something should be retrieved from disk, parsed, etc. You'll need to implement these anyways, so nothing is forced on you. 73 | 74 | ## Costume :tophat: 75 | 76 | Includes `Costume` protocol. Usage: 77 | 78 | ``` swift 79 | open class MyAppCostume : Costume { 80 | let spacing = CGFloat(8) 81 | 82 | public func wearRootBackground(_ view: UIView) { 83 | view.backgroundColor = Color.black.colorValue 84 | } 85 | 86 | public func wearHeadline(_ label: UILabel) { 87 | label.font = MyAppFont(size: .textStyle(.title1)).fontValue 88 | label.textColor = MyAppColors.forestGreen.colorValue 89 | } 90 | 91 | public var name: String { return "Default" } 92 | public var description: String { return "The default costume." } 93 | 94 | public init() { } 95 | } 96 | ``` 97 | 98 | Cheers. 99 | --------------------------------------------------------------------------------