Skip to content

Instantly share code, notes, and snippets.

@endash
Last active September 27, 2019 06:10
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save endash/acda517225dc9f4bc9db to your computer and use it in GitHub Desktop.
Save endash/acda517225dc9f4bc9db to your computer and use it in GitHub Desktop.
Photoshop style gradients in Core Graphics via use of CGShader (with thanks to @jernejstrasner, see his explanation of why your gradients might not look how your designers intended http://jernejstrasner.com/2014/01/09/smooth-gradients-ios.html) ⚠️ see comments for notes
func SineEaseInOutLinearAverage(x: Double) -> Double {
var easeInOutSine = ((cos(M_PI * x) - 1) / -2)
return (easeInOutSine + x) / 2
}
func ShadingFunctionCreate(startColor: NSColor, _ endColor: NSColor, _ slopeFunction: (Double) -> Double) -> (UnsafePointer<CGFloat>, UnsafeMutablePointer<CGFloat>) -> Void {
return { inData, outData in
let q = CGFloat(slopeFunction(Double(inData[0])))
outData[0] = startColor.redComponent + (endColor.redComponent - startColor.redComponent) * q
outData[1] = startColor.greenComponent + (endColor.greenComponent - startColor.greenComponent) * q
outData[2] = startColor.blueComponent + (endColor.blueComponent - startColor.blueComponent) * q
outData[3] = startColor.alphaComponent + (endColor.alphaComponent - startColor.alphaComponent) * q
}
}
func ShadingCallback(infoPointer: UnsafeMutablePointer<Void>, inData: UnsafePointer<CGFloat>, outData: UnsafeMutablePointer<CGFloat>) -> Void {
var info = UnsafeMutablePointer<Gradient>(infoPointer).memory
info.shadingFunction(inData, outData)
}
struct Gradient {
let startColor : NSColor
let endColor : NSColor
let from : CGPoint
let to : CGPoint
let colorSpace = NSColorSpace.genericRGBColorSpace().CGColorSpace!
init(startColor: NSColor, endColor: NSColor, from: CGPoint, to: CGPoint) {
self.startColor = startColor
self.endColor = endColor
self.from = from
self.to = to
}
lazy var shadingFunction : (UnsafePointer<CGFloat>, UnsafeMutablePointer<CGFloat>) -> Void = {
return ShadingFunctionCreate(self.startColor, self.endColor, SineEaseInOutLinearAverage)
}()
lazy var CGFunction : CGFunctionRef? = {
var callbacks = CGFunctionCallbacks(version: 0, evaluate: ShadingCallback, releaseInfo: nil)
return CGFunctionCreate(&self, 1, [0, 1], 4, [0, 1, 0, 1, 0, 1, 0, 1], &callbacks)
}()
lazy var CGShading : CGShadingRef! = CGShadingCreateAxial(self.colorSpace, self.from, self.to, self.CGFunction, false, false)
}
@LiLejia
Copy link

LiLejia commented Sep 27, 2019

Hi, I have an update for Swift 5 on iOS.
https://gist.github.com/LiLejia/3b67b5d3e0a83eb3ef251533e52a0889

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment