KMSelfSignAnnotation.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. //
  2. // KMSelfSignAnnotation.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lizhe on 2023/10/12.
  6. //
  7. import Quartz
  8. @objcMembers class KMSelfSignAnnotation: CPDFStampAnnotation {
  9. var annotationType: CAnnotationType = .unkown {
  10. didSet {
  11. let annotationModel: CPDFAnnotationModel = CPDFAnnotationModel(annotationType: annotationType)
  12. lineAnnotationWidth = annotationModel.lineWidth()
  13. lineOpacity = annotationModel.opacity()
  14. lineColor = annotationModel.color()
  15. updateAppearanceStream()
  16. }
  17. }
  18. var lineAnnotationWidth: CGFloat = 1.0
  19. var lineOpacity: CGFloat = 1.0
  20. var lineColor: NSColor = NSColor.black
  21. override init() {
  22. super.init()
  23. }
  24. func getBezierPathsArray() -> [NSBezierPath] {
  25. var lines = [NSBezierPath]()
  26. let bounds = self.bounds
  27. var bezierPath: NSBezierPath
  28. if self.annotationType == .signFalse {
  29. bezierPath = NSBezierPath()
  30. bezierPath.move(to: NSPoint(x: bounds.minX + self.lineAnnotationWidth, y: bounds.minY + self.lineAnnotationWidth))
  31. bezierPath.line(to: NSPoint(x: bounds.maxX - self.lineAnnotationWidth, y: bounds.maxY - self.lineAnnotationWidth))
  32. bezierPath.close()
  33. lines.append(bezierPath)
  34. bezierPath = NSBezierPath()
  35. bezierPath.move(to: NSPoint(x: bounds.minX + self.lineAnnotationWidth, y: bounds.maxY - self.lineAnnotationWidth))
  36. bezierPath.line(to: NSPoint(x: bounds.maxX - self.lineAnnotationWidth, y: bounds.minY + self.lineAnnotationWidth))
  37. bezierPath.close()
  38. lines.append(bezierPath)
  39. } else if self.annotationType == .signTure {
  40. bezierPath = NSBezierPath()
  41. bezierPath.move(to: NSPoint(x: bounds.minX + self.lineAnnotationWidth / 2.0, y: bounds.midY + self.lineAnnotationWidth / 2.0))
  42. bezierPath.line(to: NSPoint(x: bounds.minX + bounds.width / 3.0, y: bounds.minY + self.lineAnnotationWidth / 2.0))
  43. bezierPath.line(to: NSPoint(x: bounds.maxX - self.lineAnnotationWidth / 2.0, y: bounds.maxY - self.lineAnnotationWidth / 2.0))
  44. lines.append(bezierPath)
  45. } else if self.annotationType == .signCircle {
  46. let r = min(bounds.width, bounds.height) / 3.0
  47. bezierPath = NSBezierPath(roundedRect: bounds.insetBy(dx: self.lineAnnotationWidth / 2, dy: self.lineAnnotationWidth / 2), xRadius: r, yRadius: r)
  48. lines.append(bezierPath)
  49. bezierPath.close()
  50. } else if self.annotationType == .signLine {
  51. bezierPath = NSBezierPath()
  52. bezierPath.move(to: NSPoint(x: bounds.minX - 1, y: bounds.midY))
  53. bezierPath.line(to: NSPoint(x: bounds.maxX - 2, y: bounds.midY))
  54. bezierPath.close()
  55. lines.append(bezierPath)
  56. }
  57. return lines
  58. }
  59. func getBezierLinesArray() -> [[String]] {
  60. let lines = getBezierPathsArray()
  61. var bezierPaths = [[String]]()
  62. for bezierPath in lines {
  63. bezierPaths.append(bezierPath.getAllSignCirclePoint())
  64. }
  65. return bezierPaths
  66. }
  67. override func updateAppearanceStream() {
  68. let color = self.lineColor
  69. var red: CGFloat = 0.0
  70. var green: CGFloat = 0.0
  71. var blue: CGFloat = 0.0
  72. var alpha: CGFloat = 0.0
  73. color.usingColorSpaceName(NSColorSpaceName.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
  74. if self.annotationType == .signDot {
  75. let orgBounds = self.bounds
  76. let eProportion = min(orgBounds.size.width, orgBounds.size.height)
  77. let rect = NSRect(x: orgBounds.origin.x + (orgBounds.size.width - eProportion) / 2, y: orgBounds.origin.y + (orgBounds.size.height - eProportion) / 2, width: eProportion, height: eProportion)
  78. updateAppearanceStream(withArc: rect, border: 0, color: nil, fill: NSColor(red: red, green: green, blue: blue, alpha: self.lineOpacity))
  79. } else {
  80. let lines = getBezierLinesArray()
  81. var paths = [[NSValue]]()
  82. for line in lines {
  83. var tPoints = [NSValue]()
  84. for value in line {
  85. let pointComponents = value.components(separatedBy: ",")
  86. if pointComponents.count == 2, let x = Double(pointComponents[0]), let y = Double(pointComponents[1]) {
  87. let point = NSPoint(x: x, y: y)
  88. tPoints.append(NSValue(point: point))
  89. }
  90. }
  91. if tPoints.count > 0 {
  92. paths.append(tPoints)
  93. }
  94. }
  95. if paths.count > 0 {
  96. updateAppearanceStream(withPaths: paths, border: lineAnnotationWidth, color: NSColor(red: red, green: green, blue: blue, alpha: self.lineOpacity))
  97. }
  98. }
  99. }
  100. func draw(with box: CPDFDisplayBox, inContext context: CGContext) {
  101. var pathColor = self.lineColor
  102. var red: CGFloat = 0.0
  103. var green: CGFloat = 0.0
  104. var blue: CGFloat = 0.0
  105. var alpha: CGFloat = 0.0
  106. pathColor.usingColorSpaceName(NSColorSpaceName.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
  107. pathColor = NSColor(red: red, green: green, blue: blue, alpha: self.lineOpacity)
  108. if self.annotationType == .signTure ||
  109. self.annotationType == .signFalse ||
  110. self.annotationType == .signLine ||
  111. self.annotationType == .signCircle {
  112. for bezierPath in getBezierPathsArray() {
  113. context.addPath(createCGPath(from: bezierPath))
  114. }
  115. context.setLineWidth(lineAnnotationWidth)
  116. context.setStrokeColor(pathColor.cgColor)
  117. context.setFillColor(pathColor.cgColor)
  118. context.strokePath()
  119. } else if self.annotationType == .signDot {
  120. context.setStrokeColor(red: 0, green: 0, blue: 0, alpha: 1.0)
  121. context.setLineWidth(1.0)
  122. context.addArc(center: NSMakePoint(self.bounds.midX, self.bounds.midY), radius: min(self.bounds.width / 2.0 - 1, self.bounds.height / 2.0 - 1), startAngle: 0, endAngle: .pi * 2, clockwise: true)
  123. context.setStrokeColor(pathColor.cgColor)
  124. context.setFillColor(pathColor.cgColor)
  125. context.fillPath()
  126. }
  127. }
  128. func createCGPath(from bezierPath: NSBezierPath) -> CGPath {
  129. let path = CGMutablePath()
  130. let elementCount = bezierPath.elementCount
  131. var points = [NSPoint](repeating: .zero, count: 3)
  132. for i in 0..<elementCount {
  133. let elementType = bezierPath.element(at: i, associatedPoints: &points)
  134. switch elementType {
  135. case .moveTo:
  136. path.move(to: CGPoint(x: points[0].x, y: points[0].y))
  137. case .lineTo:
  138. path.addLine(to: CGPoint(x: points[0].x, y: points[0].y))
  139. case .curveTo:
  140. path.addCurve(to: CGPoint(x: points[2].x, y: points[2].y),
  141. control1: CGPoint(x: points[0].x, y: points[0].y),
  142. control2: CGPoint(x: points[1].x, y: points[1].y))
  143. case .closePath:
  144. path.closeSubpath()
  145. @unknown default:
  146. break
  147. }
  148. }
  149. return path
  150. }
  151. // 根据样式获取缓存的颜色
  152. static func fetchStoredColor(_ type: CAnnotationType) -> NSColor {
  153. var color = NSColor.clear
  154. if type == .signDot {
  155. color = UserDefaults.standard.color(forKey: "SKAnnotationSelfSignDotColorKey") ?? NSColor.clear
  156. } else if type == .signLine {
  157. color = UserDefaults.standard.color(forKey: "SKAnnotationSelfSignLineColorKey") ?? NSColor.clear
  158. } else if type == .signCircle {
  159. color = UserDefaults.standard.color(forKey: "SKAnnotationSelfSignCircleColorKey") ?? NSColor.clear
  160. } else if type == .signFalse {
  161. color = UserDefaults.standard.color(forKey: "SKAnnotationSelfSignFalseColorKey") ?? NSColor.clear
  162. } else if type == .signTure {
  163. color = UserDefaults.standard.color(forKey: "SKAnnotationSelfSignTureColorKey") ?? NSColor.clear
  164. }
  165. return color
  166. }
  167. static func fetchStoredLineWidth(_ type: CAnnotationType) -> CGFloat {
  168. var rtnLineWidth: CGFloat = 0
  169. if type == .signDot {
  170. rtnLineWidth = CGFloat(UserDefaults.standard.float(forKey: "SKAnnotationSelfSignDotLineWidthKey"))
  171. } else if type == .signLine {
  172. rtnLineWidth = CGFloat(UserDefaults.standard.float(forKey: "SKAnnotationSelfSignLineLineWidthKey"))
  173. } else if type == .signCircle {
  174. rtnLineWidth = CGFloat(UserDefaults.standard.float(forKey: "SKAnnotationSelfSignCircleLineWidthKey"))
  175. } else if type == .signFalse {
  176. rtnLineWidth = CGFloat(UserDefaults.standard.float(forKey: "SKAnnotationSelfSignTureLineWidthKey"))
  177. } else if type == .signTure {
  178. rtnLineWidth = CGFloat(UserDefaults.standard.float(forKey: "SKAnnotationSelfSignTureLineWidthKey"))
  179. }
  180. if rtnLineWidth == 0.0 {
  181. changeStoredLineWidth(type, lineWidth: 0.8)
  182. rtnLineWidth = 0.8
  183. }
  184. return rtnLineWidth
  185. }
  186. // 修改缓存的颜色
  187. static func changeStoredColor(_ type: CAnnotationType, color newColor: NSColor) {
  188. guard newColor.numberOfComponents > 0 else {
  189. return
  190. }
  191. let userDefaults = UserDefaults.standard
  192. if type == .signDot {
  193. userDefaults.setColor(newColor, forKey: "SKAnnotationSelfSignDotColorKey")
  194. } else if type == .signLine {
  195. userDefaults.setColor(newColor, forKey: "SKAnnotationSelfSignLineColorKey")
  196. } else if type == .signCircle {
  197. userDefaults.setColor(newColor, forKey: "SKAnnotationSelfSignCircleColorKey")
  198. } else if type == .signFalse {
  199. userDefaults.setColor(newColor, forKey: "SKAnnotationSelfSignFalseColorKey")
  200. } else if type == .signTure {
  201. userDefaults.setColor(newColor, forKey: "SKAnnotationSelfSignTrueColorKey")
  202. }
  203. }
  204. static func changeStoredLineWidth(_ type: CAnnotationType, lineWidth: CGFloat) {
  205. let userDefaults = UserDefaults.standard
  206. if type == .signDot {
  207. userDefaults.set(lineWidth, forKey: "SKAnnotationSelfSignDotLineWidthKey")
  208. } else if type == .signLine {
  209. userDefaults.set(lineWidth, forKey: "SKAnnotationSelfSignLineLineWidthKey")
  210. } else if type == .signCircle {
  211. userDefaults.set(lineWidth, forKey: "SKAnnotationSelfSignCircleLineWidthKey")
  212. } else if type == .signFalse {
  213. userDefaults.set(lineWidth, forKey: "SKAnnotationSelfSignFalseLineWidthKey")
  214. } else if type == .signTure {
  215. userDefaults.set(lineWidth, forKey: "SKAnnotationSelfSignTrueLineWidthKey")
  216. }
  217. }
  218. static func fetchSelfSignTypeString(_ type: CAnnotationType) -> String {
  219. var returnString = ""
  220. if type == .signFalse {
  221. returnString = NSLocalizedString("X", comment: "")
  222. } else if type == .signTure {
  223. returnString = NSLocalizedString("Check mark", comment: "")
  224. } else if type == .signCircle {
  225. returnString = NSLocalizedString("Circle", comment: "")
  226. } else if type == .signLine {
  227. returnString = NSLocalizedString("Line", comment: "")
  228. } else if type == .signDot {
  229. returnString = NSLocalizedString("Dot", comment: "")
  230. }
  231. return returnString
  232. }
  233. }