Created
October 20, 2016 15:26
-
-
Save erica/fe785645fb28a783e0f851b24d37dd6d to your computer and use it in GitHub Desktop.
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
import UIKit | |
func pushDraw(in context: UIGraphicsImageRendererContext, | |
applying actions: () -> Void) | |
{ | |
context.cgContext.saveGState() | |
actions() | |
context.cgContext.restoreGState() | |
} | |
let π = CGFloat(Double.pi) | |
let size = CGSize(width: 200, height: 200) | |
let renderer = UIGraphicsImageRenderer(size: size) | |
// Enable kerning | |
let attributes: [String: Any] = [ | |
NSFontAttributeName: UIFont.boldSystemFont(ofSize: 14.0), | |
NSForegroundColorAttributeName: UIColor.black, | |
NSKernAttributeName: 8 | |
] | |
// Textkit layout | |
let manager = NSLayoutManager() | |
let container = NSTextContainer(size: CGSize(width: .max, height: .max)) | |
manager.addTextContainer(container) | |
let attributedString = NSTextStorage(string: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", attributes: attributes) | |
manager.textStorage = attributedString | |
let fullSize = manager.boundingRect(forGlyphRange: NSMakeRange(0, 26), in: container).size.width | |
let lettersAndSizes = Array(0 ..< 26).lazy | |
.map({ NSMakeRange($0, 1) }) | |
.map({ (attributedString.attributedSubstring(from: $0), | |
manager.boundingRect(forGlyphRange: $0, in: container).size.width) }) | |
var consumedSize: CGFloat = 0 | |
let image = renderer.image { context in | |
let bounds = context.format.bounds | |
let (centerX, centerY) = (bounds.midX, bounds.midY) | |
// Start by adjusting the context origin | |
// This affects all subsequent operations | |
context.cgContext.translateBy(x: centerX, y: centerY) | |
// Offset by half of the first character | |
let firstHalfSize = lettersAndSizes.first!.1 / 2.0 | |
let theta = 2 * π * firstHalfSize / fullSize | |
context.cgContext.rotate(by: -theta) | |
// Set the radius to draw at | |
let r: CGFloat = 70 | |
// Draw each letter proportionally | |
for (letter, letterSize) in lettersAndSizes | |
{ | |
let halfWidth = letterSize / 2.0 | |
consumedSize = consumedSize + halfWidth; | |
defer { consumedSize += halfWidth } | |
pushDraw(in: context) { | |
// Rotate the context | |
let theta = 2 * π * consumedSize / fullSize | |
context.cgContext.rotate(by: theta) | |
// Translate up to the edge of the radius and | |
// move left by half the letter width. | |
context.cgContext.translateBy(x: -halfWidth, y: -r) | |
letter.draw(at: .zero) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment