Permalink
Browse files

Draws the path offscreen and replaces layer contents to improve perfo…

…rmance with long sets of strokes
  • Loading branch information...
DarthMike committed May 20, 2015
1 parent 5ae6497 commit 16827028b3e04e97d8cd1a5ca46c085b4fb20f12
Showing with 37 additions and 12 deletions.
  1. +37 −12 FreehandDrawing-iOS/DrawView.swift
@@ -32,13 +32,34 @@ class DrawView : UIView {
// MARK: Drawing a path
- override func drawRect(rect: CGRect) {
- // 4. Redraw whole rect, ignoring parameter. Please note we always invalidate whole view.
+ private func drawLine(a: CGPoint, b: CGPoint, buffer: UIImage?) -> UIImage {
+ let size = self.bounds.size
+
+ // Initialize a full size image. Opaque because we don't need to draw over anything. Will be more performant.
+ UIGraphicsBeginImageContextWithOptions(size, true, 0)
let context = UIGraphicsGetCurrentContext()
+
+ CGContextSetFillColorWithColor(context, self.backgroundColor?.CGColor ?? UIColor.whiteColor().CGColor)
+ CGContextFillRect(context, self.bounds)
+
+ // Draw previous buffer first
+ if let buffer = buffer {
+ buffer.drawInRect(self.bounds)
+ }
+
+ // Draw the line
self.drawColor.setStroke()
- self.path.lineWidth = self.drawWidth
- self.path.lineCapStyle = kCGLineCapRound
- self.path.stroke()
+ CGContextSetLineWidth(context, self.drawWidth)
+ CGContextSetLineCap(context, kCGLineCapRound)
+
+ CGContextMoveToPoint(context, a.x, a.y)
+ CGContextAddLineToPoint(context, b.x, b.y)
+ CGContextStrokePath(context)
+
+ // Grab the updated buffer
+ let image = UIGraphicsGetImageFromCurrentImageContext()
+ UIGraphicsEndImageContext()
+ return image
}
// MARK: Gestures
@@ -68,23 +89,27 @@ class DrawView : UIView {
// MARK: Tracing a line
private func startAtPoint(point: CGPoint) {
- self.path.moveToPoint(point)
+ self.lastPoint = point
}
private func continueAtPoint(point: CGPoint) {
- // 2. Accumulate points as they are reported by the gesture recognizer, in a bezier path object
- self.path.addLineToPoint(point)
+ // 2. Draw the current stroke in an accumulated bitmap
+ self.buffer = self.drawLine(self.lastPoint, b: point, buffer: self.buffer)
+
+ // 3. Replace the layer contents with the updated image
+ self.layer.contents = self.buffer?.CGImage ?? nil
- // 3. Trigger a redraw every time a point is added (finger moves)
- self.setNeedsDisplay()
+ // 4. Update last point for next stroke
+ self.lastPoint = point
}
private func endAtPoint(point: CGPoint) {
- // Nothing to do when ending/cancelling for now
+ self.lastPoint = CGPointZero
}
var drawColor: UIColor = UIColor.blackColor()
var drawWidth: CGFloat = 10.0
- private var path: UIBezierPath = UIBezierPath()
+ private var lastPoint: CGPoint = CGPointZero
+ private var buffer: UIImage?
}

0 comments on commit 1682702

Please sign in to comment.