Fix preserving color space for the `Color` type (#105)

Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
This commit is contained in:
hank121314 2022-06-10 15:52:03 +08:00 committed by GitHub
parent 001adc694b
commit 9e65eac602
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 35 additions and 4 deletions

View File

@ -391,10 +391,15 @@ extension Defaults {
}
extension Defaults {
/**
The bridge which is responsible for `SwiftUI.Color` serialization and deserialization.
It is unsafe to convert `SwiftUI.Color` to `UIColor` and use `UIColor.bridge` to serialize it, because `UIColor` does not hold a color space, but `Swift.Color` does (which means color space might get lost in the conversion). The bridge will always try to preserve the color space whenever `Color#cgColor` exists. Only when `Color#cgColor` is `nil`, will it use `UIColor.bridge` to do the serialization and deserialization.
*/
@available(iOS 15.0, macOS 11.0, tvOS 15.0, watchOS 8.0, iOSApplicationExtension 15.0, macOSApplicationExtension 11.0, tvOSApplicationExtension 15.0, watchOSApplicationExtension 8.0, *)
public struct ColorBridge: Bridge {
public typealias Value = Color
public typealias Serializable = Data
public typealias Serializable = Any
#if os(macOS)
private typealias NativeColor = NSColor
@ -407,15 +412,41 @@ extension Defaults {
return nil
}
return NativeColor.bridge.serialize(NativeColor(value))
guard
let cgColor = value.cgColor,
let colorSpace = cgColor.colorSpace?.name as? String,
let components = cgColor.components
else {
return NativeColor.bridge.serialize(NativeColor(value))
}
return [colorSpace, components]
}
public func deserialize(_ object: Serializable?) -> Value? {
guard let nativeColor = NativeColor.bridge.deserialize(object) else {
if let object = object as? NativeColor.Serializable {
guard let nativeColor = NativeColor.bridge.deserialize(object) else {
return nil
}
return Value(nativeColor)
}
guard
let object = object as? [Any],
let rawColorspace = object[0] as? String,
let colorspace = CGColorSpace(name: rawColorspace as CFString),
let components = object[1] as? [CGFloat],
let cgColor = CGColor(colorSpace: colorspace, components: components)
else {
return nil
}
return Value(nativeColor)
if #available(macOS 12.0, macOSApplicationExtension 12.0, *) {
return Value(cgColor: cgColor)
} else {
return Value(cgColor)
}
}
}
}