CSignatureDrawView.swift 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. //
  2. // CSignatureDrawView.swift
  3. // ComPDFKit_Tools
  4. //
  5. // Copyright © 2014-2024 PDF Technologies, Inc. All Rights Reserved.
  6. //
  7. // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
  8. // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
  9. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
  10. // This notice may not be removed from this file.
  11. //
  12. import UIKit
  13. @objc protocol CSignatureDrawViewDelegate: AnyObject {
  14. @objc optional func signatureDrawViewStart(_ signatureDrawView: CSignatureDrawView)
  15. }
  16. enum CSignatureDrawSelectedIndex: Int {
  17. case text = 0
  18. case image
  19. }
  20. class CSignatureDrawView: UIView {
  21. static var points: [CGPoint] = [
  22. CGPoint(x: 0, y: 0),
  23. CGPoint(x: 1, y: 1),
  24. CGPoint(x: 2, y: 2),
  25. CGPoint(x: 3, y: 3),
  26. CGPoint(x: 4, y: 4)
  27. ]
  28. var color: UIColor?
  29. var lineWidth: CGFloat = 0
  30. var image: UIImage?
  31. weak var delegate: CSignatureDrawViewDelegate?
  32. var selectIndex: CSignatureDrawSelectedIndex = .text
  33. private var _index: NSInteger = 0
  34. private var bezierPath: UIBezierPath?
  35. private var textRect: CGRect = .zero
  36. private var context: CGContext?
  37. // MARK: - Initializers
  38. override init(frame: CGRect) {
  39. super.init(frame: frame)
  40. bezierPath = UIBezierPath()
  41. lineWidth = 1
  42. backgroundColor = .clear
  43. }
  44. required init?(coder: NSCoder) {
  45. fatalError("init(coder:) has not been implemented")
  46. }
  47. override func layoutSubviews() {
  48. super.layoutSubviews()
  49. setNeedsDisplay(bounds)
  50. }
  51. override func draw(_ rect: CGRect) {
  52. super.draw(rect)
  53. context = UIGraphicsGetCurrentContext()
  54. if selectIndex == .text {
  55. color?.set()
  56. bezierPath?.lineWidth = lineWidth
  57. bezierPath?.lineCapStyle = .round
  58. bezierPath?.lineJoinStyle = .round
  59. bezierPath?.stroke()
  60. } else if selectIndex == .image {
  61. if let image = image {
  62. let imageFrame = imageFrameInRect(rect)
  63. image.draw(in: imageFrame)
  64. delegate?.signatureDrawViewStart?(self)
  65. }
  66. }
  67. }
  68. // MARK: - Draw Methods
  69. func imageFrameInRect(_ rect: CGRect) -> CGRect {
  70. var imageRect: CGRect = CGRect.zero
  71. if(image != nil) {
  72. if image!.size.width < rect.size.width && image!.size.height < rect.size.height {
  73. imageRect.origin.x = (rect.size.width - image!.size.width) / 2.0
  74. imageRect.origin.y = (rect.size.height - image!.size.height) / 2.0
  75. imageRect.size = image!.size
  76. } else {
  77. if image!.size.width / image!.size.height > rect.size.width / rect.size.height {
  78. imageRect.size.width = rect.size.width
  79. imageRect.size.height = rect.size.width * image!.size.height / image!.size.width
  80. } else {
  81. imageRect.size.height = rect.size.height
  82. imageRect.size.width = rect.size.height * image!.size.width / image!.size.height
  83. }
  84. imageRect.origin.x = (rect.size.width - imageRect.size.width) / 2.0
  85. imageRect.origin.y = (rect.size.height - imageRect.size.height) / 2.0
  86. }
  87. }
  88. return imageRect
  89. }
  90. // MARK: - Public Methods
  91. func signatureImage() -> UIImage? {
  92. var rect: CGRect = .zero
  93. let imageFrame = imageFrameInRect(frame)
  94. if image != nil {
  95. if bezierPath?.isEmpty ?? true {
  96. rect = imageFrame
  97. } else {
  98. let pathFrame = bezierPath?.bounds ?? .zero
  99. rect.origin.x = min(imageFrame.minX, pathFrame.minX)
  100. rect.origin.y = min(imageFrame.minY, pathFrame.minY)
  101. rect.size.width = max(imageFrame.maxX, pathFrame.maxX) - rect.origin.x
  102. rect.size.height = max(imageFrame.maxY, pathFrame.maxY) - rect.origin.y
  103. }
  104. } else {
  105. if bezierPath?.isEmpty ?? true {
  106. return nil
  107. } else {
  108. rect = bezierPath?.bounds ?? .zero
  109. }
  110. }
  111. let size = CGSize(width: rect.size.width + (bezierPath?.lineWidth ?? 0),
  112. height: rect.size.height + (bezierPath?.lineWidth ?? 0))
  113. UIGraphicsBeginImageContext(size)
  114. guard let context = UIGraphicsGetCurrentContext() else {
  115. return nil
  116. }
  117. let transform = CGAffineTransform(translationX: -rect.origin.x + (bezierPath?.lineWidth ?? 0) / 2.0,
  118. y: -rect.origin.y + (bezierPath?.lineWidth ?? 0) / 2.0)
  119. context.concatenate(transform)
  120. if let image = image {
  121. image.draw(in: imageFrame)
  122. }
  123. if !(bezierPath?.isEmpty ?? true) {
  124. if let color = color?.cgColor {
  125. context.setStrokeColor(color)
  126. }
  127. context.setLineWidth(bezierPath?.lineWidth ?? 0)
  128. context.setLineCap(bezierPath?.lineCapStyle ?? .butt)
  129. context.setLineJoin(bezierPath?.lineJoinStyle ?? .miter)
  130. if let path = bezierPath?.cgPath {
  131. context.addPath(path)
  132. }
  133. context.strokePath()
  134. }
  135. let image = UIGraphicsGetImageFromCurrentImageContext()
  136. UIGraphicsEndImageContext()
  137. return image
  138. }
  139. func signatureClear() {
  140. image = nil
  141. bezierPath?.removeAllPoints()
  142. setNeedsDisplay()
  143. }
  144. // MARK: - Action
  145. @objc func buttonItemClicked_clear(_ button: UIButton) {
  146. image = nil
  147. bezierPath?.removeAllPoints()
  148. setNeedsDisplay()
  149. }
  150. // MARK: - Touch Methods
  151. override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  152. super.touchesBegan(touches, with: event)
  153. if let point = touches.first?.location(in: self) {
  154. _index = 0
  155. CSignatureDrawView.points[0] = point
  156. delegate?.signatureDrawViewStart?(self)
  157. }
  158. }
  159. override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
  160. super.touchesMoved(touches, with: event)
  161. if let point = touches.first?.location(in: self) {
  162. _index += 1
  163. CSignatureDrawView.points[_index] = point
  164. if _index == 4 {
  165. CSignatureDrawView.points[3] = CGPoint(x: (CSignatureDrawView.points[2].x + CSignatureDrawView.points[4].x) / 2.0,
  166. y: (CSignatureDrawView.points[2].y + CSignatureDrawView.points[4].y) / 2.0)
  167. bezierPath?.move(to: CSignatureDrawView.points[0])
  168. bezierPath?.addCurve(to: CSignatureDrawView.points[3],
  169. controlPoint1: CSignatureDrawView.points[1],
  170. controlPoint2: CSignatureDrawView.points[2])
  171. CSignatureDrawView.points[0] = CSignatureDrawView.points[3]
  172. CSignatureDrawView.points[1] = CSignatureDrawView.points[4]
  173. _index = 1
  174. setNeedsDisplay()
  175. }
  176. }
  177. }
  178. override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
  179. super.touchesEnded(touches, with: event)
  180. if _index < 4 {
  181. for i in 0..<_index {
  182. bezierPath?.move(to: CSignatureDrawView.points[i])
  183. }
  184. setNeedsDisplay()
  185. }
  186. }
  187. }