|
@@ -1,375 +0,0 @@
|
|
|
-//
|
|
|
-// CPDFLineAnnotation+PDFListView.m
|
|
|
-// ComPDFKit
|
|
|
-//
|
|
|
-// Copyright © 2014-2022 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 "CPDFLineAnnotation+PDFListView.h"
|
|
|
-#import "CPDFListView+Tool.h"
|
|
|
-#import "CPDFListView+Private.h"
|
|
|
-
|
|
|
-#import "CPDFAnnotationModel.h"
|
|
|
-#import "CPDFListViewConfig.h"
|
|
|
-#import <PDF_Master-Swift.h>
|
|
|
-
|
|
|
-@implementation CPDFLineAnnotation (PDFListView)
|
|
|
-
|
|
|
-- (instancetype)initPDFListViewNoteWithDocument:(CPDFDocument *)document annotationType:(CAnnotationType)annotationType {
|
|
|
- self = [self initWithDocument:document];
|
|
|
- if (self) {
|
|
|
- CPDFAnnotationModel *annotationModel = [[CPDFAnnotationModel alloc] initWithAnnotationType:annotationType];
|
|
|
- self.color = annotationModel.color;
|
|
|
-
|
|
|
- CPDFBorder *border = [[CPDFBorder alloc] initWithStyle:annotationModel.style lineWidth:annotationModel.lineWidth dashPattern:annotationModel.dashPattern];
|
|
|
- [self setBorder:border];
|
|
|
- self.opacity = annotationModel.opacity;
|
|
|
-
|
|
|
- [self setStartLineStyle:annotationModel.startLineStyle];
|
|
|
- [self setEndLineStyle:annotationModel.endLineStyle];
|
|
|
-
|
|
|
- }
|
|
|
- return self;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)drawSelectionHighlightForView:(CPDFListView *)pdfView inContext:(CGContextRef)context isHover:(BOOL)isHover {
|
|
|
- if (NSIsEmptyRect([self bounds]))
|
|
|
- return;
|
|
|
- if ([self isResizable]) {
|
|
|
- if((pdfView.activeAnnotations.count == 1 || pdfView.selectAnnotations.count > 0) || isHover) {
|
|
|
- NSPoint point = [self startPoint];
|
|
|
- CGFloat delta = 4.0 * [pdfView unitWidthOnPage:[self page]];
|
|
|
- CPDFListViewDrawResizeHandle(context, point, delta, YES);
|
|
|
- point = [self endPoint];
|
|
|
- CPDFListViewDrawResizeHandle(context, point, delta, YES);
|
|
|
- } else {
|
|
|
- NSRect rect = [self bounds];
|
|
|
- CGFloat lineWidth = [pdfView unitWidthOnPage:[self page]];
|
|
|
- CGContextSaveGState(context);
|
|
|
- CGColorRef color = [CPDFListViewConfig defaultManager].annotationBorderColor.CGColor;
|
|
|
- CGContextSetStrokeColorWithColor(context, color);
|
|
|
-
|
|
|
- if(isHover) {
|
|
|
- CGFloat length[] = {5,5};
|
|
|
- CGContextSetLineDash(context, 0, length, 2);
|
|
|
- CGContextStrokeRectWithWidth(context, rect, lineWidth);
|
|
|
- } else {
|
|
|
- CGContextStrokeRectWithWidth(context, CGRectInset(NSRectToCGRect(rect), 0,0), lineWidth);
|
|
|
- }
|
|
|
-
|
|
|
- CGContextRestoreGState(context);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (CGRect)borderRecctForView:(CPDFListView *)pdfView{
|
|
|
- NSRect rect = [pdfView integralRect:[self bounds] onPage:[self page]];
|
|
|
- return rect;
|
|
|
-}
|
|
|
-
|
|
|
-- (BOOL)isResizable { return YES; }
|
|
|
-
|
|
|
-- (BOOL)isMovable { return YES; }
|
|
|
-
|
|
|
-- (BOOL)hitTest:(NSPoint)point {
|
|
|
- CGFloat delta = fmax(4.0, 0.5 * [self lineWidth]);
|
|
|
- return [self shouldDisplay] && CPDFListViewPointNearLineFromPointToPoint(CPDFListViewSubstractPoints(point, [self bounds].origin), CPDFListViewSubstractPoints([self observedStartPoint],[self bounds].origin), CPDFListViewSubstractPoints([self observedEndPoint],[self bounds].origin), delta);
|
|
|
-}
|
|
|
-
|
|
|
-- (CRectEdges)resizeHandleForPoint:(NSPoint)point scaleFactor:(CGFloat)scaleFactor {
|
|
|
- if ([self isResizable] == NO)
|
|
|
- return 0;
|
|
|
- NSSize size = CPDFListViewMakeSquareSize(8 / scaleFactor);
|
|
|
- if (NSPointInRect(point, CPDFListViewRectFromCenterAndSize([self endPoint], size)))
|
|
|
- return CMaxXEdgeMask;
|
|
|
- else if (NSPointInRect(point, CPDFListViewRectFromCenterAndSize([self startPoint], size)))
|
|
|
- return CMinXEdgeMask;
|
|
|
- else if ([self hitTest:point])
|
|
|
- return CEditInEdgeMask;
|
|
|
- else
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-- (NSPoint)observedStartPoint {
|
|
|
- return [self startPoint];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)setObservedStartPoint:(NSPoint)point {
|
|
|
- [self setStartPoint:point];
|
|
|
-}
|
|
|
-
|
|
|
-- (NSPoint)observedEndPoint {
|
|
|
- return [self endPoint];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)setObservedEndPoint:(NSPoint)point {
|
|
|
- [self setEndPoint:point];
|
|
|
-}
|
|
|
-
|
|
|
-- (NSSet *)keysForValuesToObserveForUndo {
|
|
|
- static NSSet *circleKeys = nil;
|
|
|
- if (circleKeys == nil) {
|
|
|
- NSMutableSet *mutableKeys = [[super keysForValuesToObserveForUndo] mutableCopy];
|
|
|
- [mutableKeys addObjectsFromArray:@[CPDFAnnotationStartPointKey,
|
|
|
- CPDFAnnotationEndPointKey,
|
|
|
- CPDFAnnotationStartLineStyleKey,
|
|
|
- CPDFAnnotationEndLineStyleKey,
|
|
|
- CPDFAnnotationInteriorOpacityKey,
|
|
|
- CPDFAnnotationInteriorColorKey]];
|
|
|
- circleKeys = mutableKeys;
|
|
|
- }
|
|
|
- return circleKeys;
|
|
|
-}
|
|
|
-
|
|
|
-+ (CGPoint)drawLineExEndingWithStyle:(CPDFLineStyle)style point:(CGPoint)point cpoint:(CGPoint)cpoint inContext:(CGContextRef)context model:(CPDFAnnotationModel *)annotationModel {
|
|
|
- CGPoint rpoint = point;
|
|
|
- switch (style) {
|
|
|
- case CPDFLineStyleOpenArrow: {
|
|
|
- CGPoint points[3];
|
|
|
- [self openArrowExPoints:points point:point cpoint:cpoint borderWidth:annotationModel.lineWidth];
|
|
|
- CGContextBeginPath(context);
|
|
|
- CGContextAddLines(context, points, 3);
|
|
|
- CGContextDrawPath(context, kCGPathStroke);
|
|
|
- }
|
|
|
- break;
|
|
|
- case CPDFLineStyleClosedArrow: {
|
|
|
- CGPoint points[3];
|
|
|
- rpoint = [self closedArrowExPoints:points point:point cpoint:cpoint];
|
|
|
- CGContextBeginPath(context);
|
|
|
- CGContextAddLines(context, points, 3);
|
|
|
- CGContextClosePath(context);
|
|
|
- CGContextDrawPath(context, kCGPathFillStroke);
|
|
|
- }
|
|
|
- break;
|
|
|
- case CPDFLineStyleSquare: {
|
|
|
- CGPoint points[4];
|
|
|
- rpoint = [self squareExPoints:points point:point cpoint:cpoint borderWidth:annotationModel.lineWidth];
|
|
|
- CGContextBeginPath(context);
|
|
|
- CGContextAddLines(context, points, 4);
|
|
|
- CGContextClosePath(context);
|
|
|
- CGContextDrawPath(context, kCGPathFillStroke);
|
|
|
- }
|
|
|
- break;
|
|
|
- case CPDFLineStyleCircle: {
|
|
|
- CGPoint points[1];
|
|
|
- rpoint = [self circleExPoints:points point:point cpoint:cpoint borderWidth:annotationModel.lineWidth];
|
|
|
- CGFloat radius = sqrt((rpoint.x - points[0].x) * (rpoint.x - points[0].x) + (rpoint.y - points[0].y) * (rpoint.y - points[0].y));
|
|
|
- CGContextBeginPath(context);
|
|
|
- CGContextAddArc(context, points[0].x, points[0].y, radius, 0, 2 * M_PI, 0);
|
|
|
- CGContextClosePath(context);
|
|
|
- CGContextDrawPath(context, kCGPathFillStroke);
|
|
|
- }
|
|
|
- break;
|
|
|
- case CPDFLineStyleDiamond: {
|
|
|
- CGPoint points[4];
|
|
|
- rpoint = [self diamondExPoints:points point:point cpoint:cpoint borderWidth:annotationModel.lineWidth];
|
|
|
- CGContextBeginPath(context);
|
|
|
- CGContextAddLines(context, points, 4);
|
|
|
- CGContextClosePath(context);
|
|
|
- CGContextDrawPath(context, kCGPathFillStroke);
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- return rpoint;
|
|
|
-}
|
|
|
-
|
|
|
-+ (CGPoint)openArrowExPoints:(CGPoint *)points point:(CGPoint)point cpoint:(CGPoint)cpoint borderWidth:(CGFloat)borderWidth {
|
|
|
- float len = 4 + borderWidth;
|
|
|
- float dx = 0, dy = 0;
|
|
|
- CGPoint point0 = CGPointZero;
|
|
|
- CGPoint point1 = CGPointZero;
|
|
|
- CGPoint point2 = CGPointZero;
|
|
|
-
|
|
|
- float 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;
|
|
|
-
|
|
|
- float 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;
|
|
|
-
|
|
|
- return point0;
|
|
|
-}
|
|
|
-
|
|
|
-+ (CGPoint)closedArrowExPoints:(CGPoint *)points point:(CGPoint)point cpoint:(CGPoint)cpoint {
|
|
|
- float len = 4;
|
|
|
- float dx = 0, dy = 0;
|
|
|
- CGPoint point0 = CGPointZero;
|
|
|
- CGPoint point1 = CGPointZero;
|
|
|
- CGPoint point2 = CGPointZero;
|
|
|
-
|
|
|
- float 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;
|
|
|
-
|
|
|
- float 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;
|
|
|
-
|
|
|
- return point0;
|
|
|
-}
|
|
|
-
|
|
|
-+ (CGPoint)squareExPoints:(CGPoint *)points point:(CGPoint)point cpoint:(CGPoint)cpoint borderWidth:(CGFloat)borderWidth {
|
|
|
- float len = MAX(4, borderWidth);
|
|
|
- float dx = 0, dy = 0;
|
|
|
- CGPoint point0 = CGPointZero;
|
|
|
- CGPoint point1 = CGPointZero;
|
|
|
- CGPoint point2 = CGPointZero;
|
|
|
- CGPoint point3 = CGPointZero;
|
|
|
- CGPoint point4 = CGPointZero;
|
|
|
- CGPoint point5 = CGPointZero;
|
|
|
- CGPoint point6 = CGPointZero;
|
|
|
-
|
|
|
- float 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;
|
|
|
-
|
|
|
- float 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;
|
|
|
-
|
|
|
- float 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;
|
|
|
-}
|
|
|
-
|
|
|
-+ (CGPoint)circleExPoints:(CGPoint *)points point:(CGPoint)point cpoint:(CGPoint)cpoint borderWidth:(CGFloat)borderWidth {
|
|
|
- float len = MAX(4, borderWidth);
|
|
|
- float dx = 0, dy = 0;
|
|
|
- CGPoint point0 = CGPointZero;
|
|
|
- CGPoint point1 = CGPointZero;
|
|
|
-
|
|
|
- float 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;
|
|
|
-}
|
|
|
-
|
|
|
-+ (CGPoint)diamondExPoints:(CGPoint *)points point:(CGPoint)point cpoint:(CGPoint)cpoint borderWidth:(CGFloat)borderWidth {
|
|
|
- float len = MAX(4, borderWidth);
|
|
|
- float dx = 0, dy = 0;
|
|
|
- CGPoint point0 = CGPointZero;
|
|
|
- CGPoint point1 = CGPointZero;
|
|
|
- CGPoint point2 = CGPointZero;
|
|
|
- CGPoint point3 = CGPointZero;
|
|
|
-
|
|
|
- float 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;
|
|
|
-
|
|
|
- float 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;
|
|
|
-}
|
|
|
-
|
|
|
-+ (NSImage *)annotationImageWithAnnotationModel:(CPDFAnnotationModel *)annotationModel{
|
|
|
- NSImage * image = [[NSImage alloc] initWithSize:CGSizeMake(50+annotationModel.lineWidth, 50+annotationModel.lineWidth)];
|
|
|
- [image lockFocus];
|
|
|
- [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
|
|
|
- CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
|
|
-
|
|
|
- CGPoint startPoint = annotationModel.annotationImageStartPoint;
|
|
|
- CGPoint endPoint = annotationModel.annotationImageEndPoint;
|
|
|
- NSColor *color = [annotationModel.color colorWithAlphaComponent:annotationModel.opacity];
|
|
|
- if (color) {
|
|
|
- CGContextSetStrokeColorWithColor(context, color.CGColor);
|
|
|
- }
|
|
|
- NSColor *interiorColor = [annotationModel.interiorColor colorWithAlphaComponent:annotationModel.opacity];
|
|
|
- if (interiorColor) {
|
|
|
- CGContextSetFillColorWithColor(context, interiorColor.CGColor);
|
|
|
- } else {
|
|
|
- CGContextSetFillColorWithColor(context, [NSColor clearColor].CGColor);
|
|
|
- }
|
|
|
- CGContextSetLineWidth(context, annotationModel.lineWidth);
|
|
|
-
|
|
|
- startPoint = [CPDFLineAnnotation drawLineExEndingWithStyle:annotationModel.startLineStyle point:startPoint cpoint:endPoint inContext:context model:annotationModel];
|
|
|
- endPoint = [CPDFLineAnnotation drawLineExEndingWithStyle:annotationModel.endLineStyle point:endPoint cpoint:startPoint inContext:context model:annotationModel];
|
|
|
- if (annotationModel.style == CPDFBorderStyleDashed &&
|
|
|
- annotationModel.dashPattern) {
|
|
|
- size_t count = annotationModel.dashPattern.count;
|
|
|
- CGFloat lengths[count];
|
|
|
- for (int i=0; i<count; i++) {
|
|
|
- lengths[i] = [annotationModel.dashPattern[i] floatValue];
|
|
|
- }
|
|
|
- CGContextSetLineDash(context, 0, lengths, count);
|
|
|
- }
|
|
|
- CGContextMoveToPoint(context, startPoint.x, startPoint.y);
|
|
|
- CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
|
|
|
- CGContextStrokePath(context);
|
|
|
-
|
|
|
- [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationDefault];
|
|
|
- [image unlockFocus];
|
|
|
- return image;
|
|
|
-}
|
|
|
-
|
|
|
-@end
|