// // CPDFSampleView.swift // ComPDFKit_Tools // // Copyright © 2014-2024 PDF Technologies, Inc. All Rights Reserved. // // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. // This notice may not be removed from this file. // import UIKit import ComPDFKit enum CPDFSamplesSelectedIndex: Int { case note = 0 case highlight case underline case strikeout case squiggly case freehand case shapeCircle case shapeSquare case shapeArrow case shapeLine case freeText case signature case stamp case image case link case sound } enum CPDFArrowStyle: Int { case none = 0 case openArrow = 1 case closedArrow = 2 case square = 3 case circle = 4 case diamond = 5 } class CPDFSampleView: UIView { var selecIndex:CPDFSamplesSelectedIndex = .highlight var startArrowStyleIndex:CPDFArrowStyle = .none var endArrowStyleIndex:CPDFArrowStyle = .none var color:UIColor? var interiorColor:UIColor? var opcity:CGFloat = 0 var thickness:CGFloat = 0 var dotted:CGFloat = 0 var familyName:String = "Helvetica" var styleName:String = "" var textAlignment:NSTextAlignment = .center var centerRect:CGRect = CGRect.zero var arrowRect:CGRect = CGRect.zero var textRect:CGRect = CGRect.zero var inkRect:CGRect = CGRect.zero override init(frame: CGRect) { super.init(frame: frame) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() setNeedsDisplay() } override func draw(_ rect: CGRect) { super.draw(rect) guard let context = UIGraphicsGetCurrentContext() else { return } centerRect = rect.insetBy(dx: (bounds.size.width/20)*9, dy: (bounds.size.height/8)*3) let centerPoint = CGPoint(x: rect.midX, y: rect.midY) arrowRect = CGRect(x: centerPoint.x-bounds.size.height/4, y: centerPoint.y-bounds.size.height/4, width: bounds.size.height/2, height: bounds.size.height/2) textRect = rect.insetBy(dx: bounds.size.width/3+3, dy: bounds.size.height/3) inkRect = rect.insetBy(dx: bounds.size.width/4, dy: bounds.size.height/3) context.setFillColor(CPDFColorUtils.CAnnotationSampleDrawBackgoundColor().cgColor) context.fill(rect) drawSamples(context: context, rect: centerRect) } func drawSamples(context: CGContext, rect: CGRect) { switch selecIndex { case .note: context.setStrokeColor(red: 0, green: 0, blue: 0, alpha: 1.0) if let color = self.color { var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 color.getRed(&red, green: &green, blue: &blue, alpha: &alpha) let updatedColor = UIColor(red: red, green: green, blue: blue, alpha: self.opcity) context.setFillColor(updatedColor.cgColor) } else { context.setStrokeColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) context.setFillColor(UIColor.clear.cgColor) } // Draw outer boxes. let width: CGFloat = 1.0 let size: CGFloat = rect.size.height / 5 var outerRect1 = rect.insetBy(dx: 0, dy: 0) outerRect1.size.height -= size var outerRect2 = outerRect1 outerRect2.origin.x += size outerRect2.origin.y += size*4 outerRect2.size.width = size outerRect2.size.height = size context.setLineWidth(width) context.move(to: CGPoint(x: outerRect1.minX, y: outerRect1.minY)) context.addLine(to: CGPoint(x: outerRect1.minX, y: outerRect1.maxY)) context.addLine(to: CGPoint(x: outerRect2.minX, y: outerRect2.minY)) context.addLine(to: CGPoint(x: outerRect2.midX, y: outerRect2.maxY)) context.addLine(to: CGPoint(x: outerRect2.midX, y: outerRect2.minY)) context.addLine(to: CGPoint(x: outerRect1.maxX, y: outerRect1.maxY)) context.addLine(to: CGPoint(x: outerRect1.maxX, y: outerRect1.minY)) context.closePath() context.drawPath(using: .fillStroke) // Draw inner lines. let count = 3 let xDelta = rect.size.width / 10 let yDelta = outerRect1.size.height / CGFloat(count + 1) var lineRect = outerRect1 lineRect.origin.x += xDelta lineRect.size.width -= 2*xDelta for i in 0.. CGPoint { var rpoint = endPoint switch style { case .openArrow: var points = [CGPoint](repeating: .zero, count: 3) rpoint = openArrowPoints(points: &points, point: endPoint, cpoint: startPoint) context.beginPath() context.addLines(between: points) context.setBlendMode(.normal) context.drawPath(using: .stroke) case .closedArrow: var points = [CGPoint](repeating: .zero, count: 3) rpoint = closedArrowPoints(points: &points, point: endPoint, cpoint: startPoint) context.beginPath() context.addLines(between: points) context.closePath() context.setBlendMode(.normal) context.drawPath(using: .stroke) case .square: var points = [CGPoint](repeating: .zero, count: 4) rpoint = squarePoints(points: &points, point: endPoint, cpoint: startPoint) context.beginPath() context.addLines(between: points) context.closePath() context.setBlendMode(.normal) context.drawPath(using: .stroke) case .circle: var points = [CGPoint](repeating: .zero, count: 1) rpoint = circlePoints(points: &points, point: endPoint, cpoint: startPoint) let radius = sqrt((rpoint.x - points[0].x) * (rpoint.x - points[0].x) + (rpoint.y - points[0].y) * (rpoint.y - points[0].y)) context.beginPath() context.addArc(center: points[0], radius: radius, startAngle: 0, endAngle: CGFloat(2 * Double.pi), clockwise: true) context.closePath() context.setBlendMode(.normal) context.drawPath(using: .stroke) case .diamond: var points = [CGPoint](repeating: .zero, count: 4) rpoint = diamondPoints(points: &points, point: endPoint, cpoint: startPoint) context.beginPath() context.addLines(between: points) context.closePath() context.setBlendMode(.normal) context.drawPath(using: .stroke) default:break } return rpoint } func openArrowPoints(points: UnsafeMutablePointer, point: CGPoint, cpoint: CGPoint) -> CGPoint { let len: CGFloat = 4 + thickness var dx: CGFloat = 0, dy: CGFloat = 0 var point0 = CGPoint.zero var point1 = CGPoint.zero var point2 = CGPoint.zero let mAB = (point.x - cpoint.x) * (point.x - cpoint.x) + (point.y - cpoint.y) * (point.y - cpoint.y) dx = (point.x - cpoint.x) * len / sqrt(mAB) dy = (point.y - cpoint.y) * len / sqrt(mAB) point0.x = point.x - dx point0.y = point.y - dy let mCB = (point.x - point0.x) * (point.x - point0.x) + (point.y - point0.y) * (point.y - point0.y) dx = -(point.y - point0.y) * len / sqrt(mCB) dy = (point.x - point0.x) * len / sqrt(mCB) point1.x = point0.x + dx point1.y = point0.y + dy point2.x = 2 * point0.x - point1.x point2.y = 2 * point0.y - point1.y // Assuming points is an array of CGPoint points[0] = point1 points[1] = point points[2] = point2 return point0 } func closedArrowPoints(points: UnsafeMutablePointer, point: CGPoint, cpoint: CGPoint) -> CGPoint { let len: CGFloat = 4 var dx: CGFloat = 0, dy: CGFloat = 0 var point0 = CGPoint.zero var point1 = CGPoint.zero var point2 = CGPoint.zero let mAB = (point.x - cpoint.x) * (point.x - cpoint.x) + (point.y - cpoint.y) * (point.y - cpoint.y) dx = (point.x - cpoint.x) * len / sqrt(mAB) dy = (point.y - cpoint.y) * len / sqrt(mAB) point0.x = point.x - dx point0.y = point.y - dy let mCB = (point.x - point0.x) * (point.x - point0.x) + (point.y - point0.y) * (point.y - point0.y) dx = -(point.y - point0.y) * len / sqrt(mCB) dy = (point.x - point0.x) * len / sqrt(mCB) point1.x = point0.x + dx point1.y = point0.y + dy point2.x = 2 * point0.x - point1.x point2.y = 2 * point0.y - point1.y // Assuming points is an array of CGPoint points[0] = point1 points[1] = point points[2] = point2 return point0 } func squarePoints(points: UnsafeMutablePointer, point: CGPoint, cpoint: CGPoint) -> CGPoint { let len = max(4, thickness) var dx: CGFloat = 0, dy: CGFloat = 0 var point0 = CGPoint.zero var point1 = CGPoint.zero var point2 = CGPoint.zero var point3 = CGPoint.zero var point4 = CGPoint.zero var point5 = CGPoint.zero var point6 = CGPoint.zero let mAB = (point.x - cpoint.x) * (point.x - cpoint.x) + (point.y - cpoint.y) * (point.y - cpoint.y) dx = (point.x - cpoint.x) * len / sqrt(mAB) dy = (point.y - cpoint.y) * len / sqrt(mAB) point0.x = point.x - dx point0.y = point.y - dy point5.x = point.x - 2 * dx point5.y = point.y - 2 * dy point6.x = point.x + dx point6.y = point.y + dy let mCD = (point0.x - point5.x) * (point0.x - point5.x) + (point0.y - point5.y) * (point0.y - point5.y) dx = -(point0.y - point5.y) * len / sqrt(mCD) dy = (point0.x - point5.x) * len / sqrt(mCD) point1.x = point5.x + dx point1.y = point5.y + dy point2.x = 2 * point5.x - point1.x point2.y = 2 * point5.y - point1.y let mEB = (point6.x - point.x) * (point6.x - point.x) + (point6.y - point.y) * (point6.y - point.y) dx = -(point6.y - point.y) * len / sqrt(mEB) dy = (point6.x - point.x) * len / sqrt(mEB) point3.x = point.x + dx point3.y = point.y + dy point4.x = 2 * point.x - point3.x point4.y = 2 * point.y - point3.y points[0] = point1 points[1] = point3 points[2] = point4 points[3] = point2 return point5 } func circlePoints(points: UnsafeMutablePointer, point: CGPoint, cpoint: CGPoint) -> CGPoint { let len = max(4, thickness) var dx: CGFloat = 0, dy: CGFloat = 0 var point0 = CGPoint.zero var point1 = CGPoint.zero let mAB = (point.x - cpoint.x) * (point.x - cpoint.x) + (point.y - cpoint.y) * (point.y - cpoint.y) dx = (point.x - cpoint.x) * len / sqrt(mAB) dy = (point.y - cpoint.y) * len / sqrt(mAB) point0.x = point.x - dx point0.y = point.y - dy point1.x = point.x - 2 * dx point1.y = point.y - 2 * dy points[0] = point0 return point1 } func diamondPoints(points: UnsafeMutablePointer, point: CGPoint, cpoint: CGPoint) -> CGPoint { let len = max(4, thickness) var dx: CGFloat = 0, dy: CGFloat = 0 var point0 = CGPoint.zero var point1 = CGPoint.zero var point2 = CGPoint.zero var point3 = CGPoint.zero let mAB = (point.x - cpoint.x) * (point.x - cpoint.x) + (point.y - cpoint.y) * (point.y - cpoint.y) dx = (point.x - cpoint.x) * len / sqrt(mAB) dy = (point.y - cpoint.y) * len / sqrt(mAB) point0.x = point.x - dx point0.y = point.y - dy point3.x = point.x - 2 * dx point3.y = point.y - 2 * dy let mCB = (point.x - point0.x) * (point.x - point0.x) + (point.y - point0.y) * (point.y - point0.y) dx = -(point.y - point0.y) * len / sqrt(mCB) dy = (point.x - point0.x) * len / sqrt(mCB) point1.x = point0.x + dx point1.y = point0.y + dy point2.x = 2 * point0.x - point1.x point2.y = 2 * point0.y - point1.y points[0] = point1 points[1] = point points[2] = point2 points[3] = point3 return point3 } }