Last active
May 24, 2022 22:24
-
-
Save BenziAhamed/bcbed0054a6b572c9d8d to your computer and use it in GitHub Desktop.
Demonstration of using CGCreatePattern in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: Playground - noun: a place where people can play | |
//: Copy this to one! | |
import UIKit | |
// With helpful insights from | |
// https://forums.developer.apple.com/message/15725#15725 via http://oleb.net/blog/2015/06/c-callbacks-in-swift/ | |
// This is essential the standalone basic definition of a pattern | |
// that CGCreatePattern requires | |
public class PatternDefinition : NSObject { | |
public let size:CGSize | |
public var bounds:CGRect | |
public var colored:Bool = true | |
public var xStep:CGFloat = 0 | |
public var yStep:CGFloat = 0 | |
public var tiling = CGPatternTiling.ConstantSpacing | |
public var transform:CGAffineTransform = CGAffineTransformMake(1, 0, 0, 1, 0, 0) | |
public init(size:CGSize) { | |
self.size = size | |
self.bounds = CGRectMake(0, 0, size.width, size.height) | |
self.xStep = size.width | |
self.yStep = size.height | |
} | |
} | |
// A block that can create a pattern for a context from a definition | |
public typealias PatternCreationBlock = @convention(block) (PatternDefinition, CGContext?) -> Void | |
// The pattern payload consists of the pattern definition | |
// and a block that given a CG context and pattern definition | |
// will draw a pattern in the context | |
public class PatternPayload : NSObject { | |
public let definition:PatternDefinition | |
public let createBlock:PatternCreationBlock | |
public init(definition:PatternDefinition, createBlock:PatternCreationBlock) { | |
self.definition = definition | |
self.createBlock = createBlock | |
} | |
} | |
public struct DrawKit { | |
public static func createPatternImage(size:CGSize, payload:PatternPayload) -> UIImage { | |
// This is the C-style function that will be called via CGCreatePattern | |
// we extract the payload, and call its create block which will | |
// draw the desired pattern in the context | |
func drawPattern(info:UnsafeMutablePointer<Void>, context:CGContext?) -> Void { | |
let payload = unsafeBitCast(info, PatternPayload.self) | |
payload.createBlock(payload.definition, context) | |
} | |
UIGraphicsBeginImageContext(size) | |
let context = UIGraphicsGetCurrentContext() | |
CGContextSaveGState(context) | |
CGContextSetAllowsAntialiasing(context, false) | |
let patternSpace = CGColorSpaceCreatePattern(nil) | |
CGContextSetFillColorSpace(context, patternSpace) | |
var callbacks = CGPatternCallbacks(version: 0, drawPattern: drawPattern, releaseInfo: nil) | |
let def = payload.definition | |
let pattern = CGPatternCreate( | |
unsafeBitCast(payload, UnsafeMutablePointer<Void>.self), // oooh! | |
def.bounds, | |
def.transform, | |
def.xStep, | |
def.yStep, | |
def.tiling, | |
def.colored, | |
&callbacks | |
) | |
var alpha:CGFloat = 1 | |
CGContextSetFillPattern(context, pattern, &alpha) | |
CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height)) | |
CGContextRestoreGState(context) | |
let image = UIGraphicsGetImageFromCurrentImageContext() | |
UIGraphicsEndImageContext() | |
return image | |
} | |
} | |
// ------- let's create a pattern filled image | |
let createPatternBlock: PatternCreationBlock = { | |
(def, context) in | |
CGContextSetFillColorWithColor(context, UIColor.redColor().CGColor) | |
CGContextFillRect(context, CGRectMake(0, 0, def.size.width, def.size.height)) | |
CGContextSetFillColorWithColor(context, UIColor.blackColor().colorWithAlphaComponent(0.2).CGColor) | |
CGContextFillRect(context, CGRectMake(2, 2, def.size.width-2, def.size.height-2)) | |
return | |
} | |
let pattern = PatternDefinition(size: CGSizeMake(10,10)) | |
let image = DrawKit.createPatternImage(CGSizeMake(300, 200), payload: PatternPayload(definition: pattern, createBlock: createPatternBlock)) | |
Author
BenziAhamed
commented
Sep 19, 2015
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment