KMPDFAnnotationChoiceWidgetSub.swift 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. //
  2. // KMPDFAnnotationChoiceWidgetSub.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by wanjun on 2024/1/31.
  6. //
  7. import Cocoa
  8. class KMPDFAnnotationChoiceWidgetSub: CPDFChoiceWidgetAnnotation {
  9. var formType: CAnnotationType = .unkown
  10. override func draw(with box: CPDFDisplayBox, in context: CGContext!) {
  11. let listChoice: Bool = isListChoice
  12. if listChoice {
  13. if hasAppearanceStream() {
  14. super.draw(with: box, in: context)
  15. } else {
  16. super.draw(with: box, in: context)
  17. transformContext(for: page, displayBox: box)
  18. context.setStrokeColor(red: 0, green: 0, blue: 0, alpha: 1.0)
  19. context.setLineWidth(1.0)
  20. context.addRect(CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width, height: bounds.size.height))
  21. context.strokePath()
  22. }
  23. } else {
  24. if hasAppearanceStream() {
  25. super.draw(with: box, in: context)
  26. } else {
  27. var stabilizeHeight = bounds.size.height
  28. if stabilizeHeight > 25.0 {
  29. stabilizeHeight = 25.0
  30. }
  31. var actualRect = CGRect.zero
  32. actualRect = CGRect(x: bounds.origin.x, y: bounds.minY + (bounds.height - stabilizeHeight) / 2, width: bounds.size.width, height: stabilizeHeight)
  33. let borderWidth: CGFloat = 0.5
  34. var rightPartWidthChangePointValue = bounds.size.width / 2
  35. if rightPartWidthChangePointValue > 30 {
  36. rightPartWidthChangePointValue = 30
  37. }
  38. let radius: CGFloat = 2.0
  39. // 画外框
  40. context.saveGState()
  41. context.move(to: CGPoint(x: actualRect.maxX - rightPartWidthChangePointValue, y: actualRect.minY + borderWidth))
  42. context.addLine(to: CGPoint(x: actualRect.minX + borderWidth, y: actualRect.minY + borderWidth))
  43. context.addLine(to: CGPoint(x: actualRect.minX + borderWidth, y: actualRect.maxY - borderWidth))
  44. context.addLine(to: CGPoint(x: actualRect.maxX - rightPartWidthChangePointValue + 2 * borderWidth, y: actualRect.maxY - borderWidth))
  45. context.addLine(to: CGPoint(x: actualRect.maxX - rightPartWidthChangePointValue + 2 * borderWidth, y: actualRect.minY + borderWidth))
  46. context.setStrokeColor(NSColor.lightGray.cgColor)
  47. context.setLineWidth(borderWidth)
  48. context.setFillColor(self.backgroundColor.cgColor)
  49. context.drawPath(using: .fillStroke)
  50. context.restoreGState()
  51. context.saveGState()
  52. context.move(to: CGPoint(x: actualRect.maxX - rightPartWidthChangePointValue, y: actualRect.maxY))
  53. context.addLine(to: CGPoint(x: actualRect.maxX - rightPartWidthChangePointValue, y: actualRect.minY))
  54. context.addLine(to: CGPoint(x: actualRect.maxX - radius, y: actualRect.minY))
  55. context.addArc(center: CGPoint(x: actualRect.maxX - radius, y: actualRect.minY + radius), radius: radius, startAngle: CGFloat(3 * Double.pi / 2), endAngle: CGFloat(2 * Double.pi), clockwise: false)
  56. context.addLine(to: CGPoint(x: actualRect.maxX, y: actualRect.maxY - radius))
  57. context.addArc(center: CGPoint(x: actualRect.maxX - radius, y: actualRect.maxY - radius), radius: radius, startAngle: CGFloat(2 * Double.pi), endAngle: CGFloat(Double.pi / 2), clockwise: false)
  58. context.addLine(to: CGPoint(x: actualRect.maxX - rightPartWidthChangePointValue, y: actualRect.maxY))
  59. context.setFillColor(NSColor(red: 37/255.0, green: 139/255.0, blue: 251/255.0, alpha: 1.0).cgColor)
  60. context.drawPath(using: .fill)
  61. context.restoreGState()
  62. // 画等边三角形
  63. let triangleWidth = min(rightPartWidthChangePointValue, actualRect.height) / 2.0
  64. let triangleHeight = triangleWidth * sqrt(3.0) / 2
  65. let centerPointUpGap = triangleHeight / 3.0
  66. context.saveGState()
  67. let startPointX = actualRect.maxX - rightPartWidthChangePointValue + (rightPartWidthChangePointValue - triangleWidth) / 2
  68. let startPointY = actualRect.midY + centerPointUpGap
  69. context.move(to: CGPoint(x: startPointX, y: startPointY))
  70. context.addLine(to: CGPoint(x: startPointX + triangleWidth, y: startPointY))
  71. context.addLine(to: CGPoint(x: startPointX + triangleWidth / 2.0, y: actualRect.midY - 2 * centerPointUpGap))
  72. context.closePath()
  73. context.setFillColor(NSColor.white.cgColor)
  74. context.drawPath(using: .fill)
  75. context.restoreGState()
  76. context.saveGState()
  77. // 画文字
  78. var attributes = [NSAttributedString.Key: Any]()
  79. if let font = self.font {
  80. attributes[.font] = font
  81. }
  82. if let fontColor = self.fontColor {
  83. attributes[.foregroundColor] = fontColor
  84. }
  85. let stringRect = self.string().boundingRect(with: CGSize(width: actualRect.size.width - rightPartWidthChangePointValue, height: actualRect.size.height), options: .usesLineFragmentOrigin, attributes: attributes)
  86. self.string().draw(in: CGRect(x: actualRect.origin.x, y: (actualRect.size.height - stringRect.size.height) / 2 + actualRect.origin.y, width: stringRect.size.width, height: stringRect.size.height), withAttributes: attributes)
  87. // context.restoreGState()
  88. }
  89. }
  90. }
  91. func transformContext(for page: CPDFPage, displayBox box: CPDFDisplayBox) {
  92. var transform = NSAffineTransform()
  93. // Identity.
  94. transform = NSAffineTransform()
  95. // Bounds for page.
  96. let boxRect = page.bounds(for: box)
  97. // Handle rotation.
  98. let rotation = page.rotation
  99. switch rotation {
  100. case 90:
  101. transform.rotate(byDegrees: -90)
  102. transform.translateX(by: -boxRect.size.width, yBy: 0.0)
  103. case 180:
  104. transform.rotate(byDegrees: 180)
  105. transform.translateX(by: -boxRect.size.width, yBy: -boxRect.size.height)
  106. case 270:
  107. transform.rotate(byDegrees: 90)
  108. transform.translateX(by: 0.0, yBy: -boxRect.size.height)
  109. default:
  110. break
  111. }
  112. // Origin.
  113. transform.translateX(by: -boxRect.origin.x, yBy: -boxRect.origin.y)
  114. // Concatenate.
  115. transform.concat()
  116. }
  117. func keysForValuesToObserveForUndo() -> Set<String> {
  118. return []
  119. }
  120. }