Skip to content

Instantly share code, notes, and snippets.

@LiLejia
Last active September 27, 2019 06:09
Show Gist options
  • Save LiLejia/3b67b5d3e0a83eb3ef251533e52a0889 to your computer and use it in GitHub Desktop.
Save LiLejia/3b67b5d3e0a83eb3ef251533e52a0889 to your computer and use it in GitHub Desktop.
An update of @endash https://gist.github.com/endash/acda517225dc9f4bc9db for Swift 5. New `UnsafeMutableRawPointer` is a little tricky. See [here](https://www.raywenderlich.com/780-unsafe-swift-using-pointers-and-interacting-with-c). Photoshop style gradients in Core Graphics via use of CGShader (with thanks to @jernejstrasner, see his explanati…
import UIKit
func SineEaseInOutLinearAverage(x: CGFloat) -> CGFloat {
let easeInOutSine = ((cos(CGFloat.pi * x) - 1) / -2)
return (easeInOutSine + x) / 2
}
func ShadingFunctionCreate(_ startColor: UIColor, _ endColor: UIColor, _ slopeFunction: @escaping (CGFloat) -> CGFloat) -> (UnsafePointer<CGFloat>, UnsafeMutablePointer<CGFloat>) -> Void {
return { inData, outData in
let q = slopeFunction(inData[0])
let startComponents = startColor.cgColor.components!
let endCOmponets = endColor.cgColor.components!
outData[0] = startComponents[0] + (endCOmponets[0] - startComponents[0]) * q
outData[1] = startComponents[1] + (endCOmponets[1] - startComponents[1]) * q
outData[2] = startComponents[2] + (endCOmponets[2] - startComponents[2]) * q
outData[3] = startComponents[3] + (endCOmponets[3] - startComponents[3]) * q
}
}
func ShadingCallback(infoPointer: UnsafeMutableRawPointer?, inData: UnsafePointer<CGFloat>, outData: UnsafeMutablePointer<CGFloat>) -> Void {
if var info = infoPointer?.load(as: Gradient.self) {
info.shadingFunction(inData, outData)
}
}
struct Gradient {
let startColor : UIColor
let endColor : UIColor
let from : CGPoint
let to : CGPoint
let colorSpace = CGColorSpaceCreateDeviceRGB()
init(startColor: UIColor, endColor: UIColor, 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 : CGFunction? = {
var callbacks = CGFunctionCallbacks(version: 0, evaluate: ShadingCallback, releaseInfo: nil)
let byteCount = MemoryLayout<Gradient>.size
let alignment = MemoryLayout<Gradient>.alignment
let infoPointer = UnsafeMutableRawPointer.allocate(byteCount: byteCount, alignment: alignment)
infoPointer.storeBytes(of: self, as: Gradient.self)
defer{
infoPointer.deallocate()
}
return CGFunction(info: infoPointer, domainDimension: 1, domain: [0, 1], rangeDimension: 4, range: [0, 1, 0, 1, 0, 1, 0, 1], callbacks: &callbacks)
}()
lazy var cgShading : CGShading! = CGShading(axialSpace: self.colorSpace, start: self.from, end: self.to, function: self.cgfunction!, extendStart: false, extendEnd: false)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment