|
@@ -1,303 +0,0 @@
|
|
|
-//
|
|
|
-// CPDFInkAnnotation+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 "CPDFInkAnnotation+PDFListView.h"
|
|
|
-#import "NSBezierPath+PDFListView.h"
|
|
|
-#import "NSGraphics+PDFListView.h"
|
|
|
-#import "NSGeometry+PDFListView.h"
|
|
|
-#import "CPDFAnnotationModel.h"
|
|
|
-#import <PDF_Master-Swift.h>
|
|
|
-
|
|
|
-@implementation CPDFInkAnnotation (PDFListView)
|
|
|
-
|
|
|
-- (instancetype)initPDFListViewNoteWithDocument:(CPDFDocument *)document{
|
|
|
- self = [self initWithDocument:document];
|
|
|
- if (self) {
|
|
|
- CPDFAnnotationModel *annotationModel = [[CPDFAnnotationModel alloc] initWithAnnotationType:CAnnotationTypeInk];
|
|
|
- self.color = annotationModel.color;
|
|
|
- self.border = [[CPDFBorder alloc] initWithStyle:annotationModel.style lineWidth:annotationModel.lineWidth dashPattern:annotationModel.dashPattern];
|
|
|
- self.opacity = annotationModel.opacity;
|
|
|
- }
|
|
|
- return self;
|
|
|
-}
|
|
|
-
|
|
|
-- (id)initPDFListViewNoteWithPaths:(NSArray <NSBezierPath *>*)paths document:(CPDFDocument *)pdfDocument{
|
|
|
- self = [self initWithDocument:pdfDocument];
|
|
|
- if (self) {
|
|
|
- [self setBezierPaths:paths];
|
|
|
- CPDFAnnotationModel *annotationModel = [[CPDFAnnotationModel alloc] initWithAnnotationType:CAnnotationTypeInk];
|
|
|
- self.color = annotationModel.color;
|
|
|
- self.borderWidth = annotationModel.lineWidth;
|
|
|
- CPDFBorder *cBorder = [[CPDFBorder alloc] initWithStyle:annotationModel.style lineWidth:annotationModel.lineWidth dashPattern:annotationModel.dashPattern];
|
|
|
- self.border = cBorder;
|
|
|
- self.opacity = annotationModel.opacity;
|
|
|
- [self updateAppearanceInkWithIsAdd:NO];
|
|
|
- }
|
|
|
- return self;
|
|
|
-}
|
|
|
-
|
|
|
-- (NSSet *)keysForValuesToObserveForUndo {
|
|
|
- static NSSet *circleKeys = nil;
|
|
|
- if (circleKeys == nil) {
|
|
|
- NSMutableSet *mutableKeys = [[super keysForValuesToObserveForUndo] mutableCopy];
|
|
|
- [mutableKeys addObjectsFromArray:@[CPDFAnnotationPathsKey]];
|
|
|
- circleKeys = [mutableKeys copy];
|
|
|
- }
|
|
|
- return circleKeys;
|
|
|
-}
|
|
|
-
|
|
|
-- (CGFloat)lineWidth {
|
|
|
- return [self borderWidth];
|
|
|
-}
|
|
|
-
|
|
|
-- (BOOL)isResizable {
|
|
|
- return YES;
|
|
|
-}
|
|
|
-
|
|
|
-- (BOOL)isMovable {
|
|
|
- return YES;
|
|
|
-}
|
|
|
-
|
|
|
-+ (void)addPoint:(NSPoint)point toCNotesPath:(NSBezierPath *)path {
|
|
|
- NSUInteger count = [path elementCount];
|
|
|
- if (count == 0) {
|
|
|
- [path moveToPoint:point];
|
|
|
- } else if (count == 1) {
|
|
|
- [path lineToPoint:point];
|
|
|
- } else {
|
|
|
- NSBezierPathElement elt;
|
|
|
- NSPoint points[3];
|
|
|
- NSPoint diff, controlPoint, point0, point1;
|
|
|
- CGFloat t, dInv, d0, d1;
|
|
|
-
|
|
|
- elt = [path elementAtIndex:count - 2 associatedPoints:points];
|
|
|
- point0 = elt == NSCurveToBezierPathElement ? points[2] : points[0];
|
|
|
-
|
|
|
- elt = [path elementAtIndex:count - 1 associatedPoints:points];
|
|
|
- point1 = elt == NSCurveToBezierPathElement ? points[2] : points[0];
|
|
|
-
|
|
|
- diff.x = point.x - point0.x;
|
|
|
- diff.y = point.y - point0.y;
|
|
|
-
|
|
|
- d0 = fabs((point1.x - point0.x) * diff.x + (point1.y - point0.y) * diff.y);
|
|
|
- d1 = fabs((point.x - point1.x) * diff.x + (point.y - point1.y) * diff.y);
|
|
|
- dInv = d0 + d1 > 0.0 ? 1.0 / (3.0 * (d0 + d1)) : 0.0;
|
|
|
-
|
|
|
- t = d0 * dInv;
|
|
|
- controlPoint.x = point1.x - t * diff.x;
|
|
|
- controlPoint.y = point1.y - t * diff.y;
|
|
|
-
|
|
|
- if (elt == NSCurveToBezierPathElement) {
|
|
|
- points[1] = controlPoint;
|
|
|
- [path setAssociatedPoints:points atIndex:count - 1];
|
|
|
- } else if (count == 2) {
|
|
|
- [path removeAllPoints];
|
|
|
- [path moveToPoint:point0];
|
|
|
- [path curveToPoint:point1 controlPoint1:point0 controlPoint2:controlPoint];
|
|
|
- }
|
|
|
-
|
|
|
- t = d1 * dInv;
|
|
|
- controlPoint.x = point1.x + t * diff.x;
|
|
|
- controlPoint.y = point1.y + t * diff.y;
|
|
|
-
|
|
|
- [path curveToPoint:point controlPoint1:controlPoint controlPoint2:point];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//- (BOOL)hitTest:(NSPoint)point {
|
|
|
-// if ([super hitTest:point] == NO)
|
|
|
-// return NO;
|
|
|
-//
|
|
|
-// CGFloat delta = fmax(4.0, 0.5 * [self lineWidth]);
|
|
|
-// for (NSBezierPath *path in [self bezierPaths]) {
|
|
|
-// if (NSPointInRect(point, NSInsetRect([path nonPDFListViewEmptyBounds], -delta, -delta))) {
|
|
|
-// NSBezierPathElement elt;
|
|
|
-// NSPoint prevPoint, nextPoint = NSZeroPoint, points[3];
|
|
|
-// NSUInteger i, iMax = [path elementCount];
|
|
|
-//
|
|
|
-// for (i = 0; i < iMax; i++) {
|
|
|
-//
|
|
|
-// prevPoint = nextPoint;
|
|
|
-// elt = [path elementAtIndex:i associatedPoints:points];
|
|
|
-//
|
|
|
-// if (elt == NSCurveToBezierPathElement) {
|
|
|
-// NSPoint min = prevPoint, max = prevPoint;
|
|
|
-// NSBezierPath *flattenedPath;
|
|
|
-// NSUInteger j, jMax;
|
|
|
-//
|
|
|
-// for (j = 0; j < 3; j++) {
|
|
|
-// min.x = fmin(min.x, points[j].x);
|
|
|
-// min.y = fmin(min.y, points[j].y);
|
|
|
-// max.x = fmax(max.x, points[j].x);
|
|
|
-// max.y = fmax(max.y, points[j].y);
|
|
|
-// }
|
|
|
-// if (point.x < min.x - delta || point.y < min.y - delta || point.x > max.x + delta || point.y > max.y + delta) {
|
|
|
-// nextPoint = points[2];
|
|
|
-// } else {
|
|
|
-// flattenedPath = [NSBezierPath bezierPath];
|
|
|
-// [flattenedPath moveToPoint:prevPoint];
|
|
|
-// [flattenedPath curveToPoint:points[0] controlPoint1:points[1] controlPoint2:points[2]];
|
|
|
-// flattenedPath = [flattenedPath bezierPathByFlatteningPath];
|
|
|
-// jMax = [flattenedPath elementCount];
|
|
|
-// for (j = 1; j < jMax; j++) {
|
|
|
-// prevPoint = nextPoint;
|
|
|
-// nextPoint = [flattenedPath associatedPDListViewPointForElementAtIndex:j];
|
|
|
-// if (CPDFListViewPointNearLineFromPointToPoint(point, prevPoint, nextPoint, delta))
|
|
|
-// return YES;
|
|
|
-// }
|
|
|
-// }
|
|
|
-// } else {
|
|
|
-// nextPoint = points[0];
|
|
|
-// if (elt != NSMoveToBezierPathElement && CPDFListViewPointNearLineFromPointToPoint(point, prevPoint, nextPoint, delta))
|
|
|
-// return YES;
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// return NO;
|
|
|
-//}
|
|
|
-
|
|
|
-+ (NSImage *)annotationImageWithAnnotationModel:(CPDFAnnotationModel *)annotationModel{
|
|
|
- CGRect bounds = annotationModel.annotationImageBounds;
|
|
|
- NSImage * image = [[NSImage alloc] initWithSize:annotationModel.annotationImageBounds.size];
|
|
|
- [image lockFocus];
|
|
|
- [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
|
|
|
- CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
|
|
- CGFloat lineWidth = annotationModel.lineWidth;
|
|
|
- if(annotationModel.annotationType == CAnnotationTypeEraser) {
|
|
|
- CGContextSetRGBStrokeColor(context, 0, 0, 0, 1.0);
|
|
|
- CGContextSetLineWidth(context, 1.0);
|
|
|
- CGContextAddArc(context, CGRectGetMidX(bounds), CGRectGetMidY(bounds), lineWidth, 0, M_PI * 2, YES);
|
|
|
- CGContextSetStrokeColorWithColor(context, [NSColor grayColor].CGColor);
|
|
|
- CGContextSetFillColorWithColor(context, [NSColor grayColor].CGColor);
|
|
|
- CGContextFillPath(context);
|
|
|
- [image unlockFocus];
|
|
|
- } else {
|
|
|
- CGFloat width = image.size.width/3.0;
|
|
|
- CGFloat height = image.size.height/2.0;
|
|
|
- CGContextMoveToPoint(context, 0, height);
|
|
|
- CGContextAddCurveToPoint(context,
|
|
|
- width,height+25,
|
|
|
- width*2.0,height-25,
|
|
|
- width*3.0,height);
|
|
|
- CGContextSetLineWidth(context, annotationModel.lineWidth);
|
|
|
- NSColor *color = annotationModel.color;
|
|
|
- CGFloat red,green,blue,alpha;
|
|
|
- if (color) {
|
|
|
- [[color colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&red green:&green blue:&blue alpha:&alpha];
|
|
|
- } else {
|
|
|
- [[[NSColor whiteColor] colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&red green:&green blue:&blue alpha:&alpha];
|
|
|
- }
|
|
|
- NSColor *noteColor = [NSColor colorWithRed:red green:green blue:blue alpha:annotationModel.opacity];
|
|
|
- CGContextSetStrokeColorWithColor(context, noteColor.CGColor);
|
|
|
- if (CPDFBorderStyleDashed == annotationModel.style) {
|
|
|
- NSArray *dashPattern = annotationModel.dashPattern;
|
|
|
- if (dashPattern.count > 0) {
|
|
|
- CGFloat lengths[dashPattern.count];
|
|
|
- for (NSUInteger i=0; i<dashPattern.count; i++) {
|
|
|
- lengths[i] = [dashPattern[i] floatValue];
|
|
|
- }
|
|
|
- CGContextSetLineDash(context, 0, lengths, dashPattern.count);
|
|
|
- }
|
|
|
- }
|
|
|
- CGContextStrokePath(context);
|
|
|
- [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationDefault];
|
|
|
- [image unlockFocus];
|
|
|
- }
|
|
|
- return image;
|
|
|
-}
|
|
|
-
|
|
|
-+ (NSImage *)pathsImage:(CPDFInkAnnotation *)annotation {
|
|
|
- if (annotation == nil) {
|
|
|
- return nil;
|
|
|
- }
|
|
|
- CPDFAnnotationModel *model = [[CPDFAnnotationModel alloc] initWithPDFAnnotations:@[annotation]];
|
|
|
- CGFloat minX = CGFLOAT_MAX;
|
|
|
- CGFloat minY = CGFLOAT_MAX;
|
|
|
- CGFloat maxX = CGFLOAT_MIN;
|
|
|
- CGFloat maxY = CGFLOAT_MIN;
|
|
|
-
|
|
|
- int count = 0;
|
|
|
- for (int i = 0; i < annotation.paths.count; i++) {
|
|
|
- NSArray *tempArray = annotation.paths[i];
|
|
|
- for (int j = 0; j < tempArray.count; j++) {
|
|
|
- CGPoint point = [tempArray[j] pointValue];
|
|
|
- //获取最大值和最小值
|
|
|
- if (point.x < minX) {
|
|
|
- minX = point.x;
|
|
|
- }
|
|
|
- if (point.y < minY) {
|
|
|
- minY = point.y;
|
|
|
- }
|
|
|
- if (point.x > maxX) {
|
|
|
- maxX = point.x;
|
|
|
- }
|
|
|
- if (point.y > maxY) {
|
|
|
- maxY = point.y;
|
|
|
- }
|
|
|
- count ++;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (count == 0) {
|
|
|
- return nil;
|
|
|
- }
|
|
|
-
|
|
|
- if (count <= 2) {
|
|
|
- minX = minX - 10;
|
|
|
- maxX = maxX + 10;
|
|
|
- minY = minY - 10;
|
|
|
- maxY = maxY + 10;
|
|
|
- }
|
|
|
-
|
|
|
- minX = minX - model.lineWidth * 2;
|
|
|
- maxX = maxX + model.lineWidth * 2;
|
|
|
- minY = minY - model.lineWidth * 2;
|
|
|
- maxY = maxY + model.lineWidth * 2;
|
|
|
-
|
|
|
- NSColor *color = model.color;
|
|
|
- CGFloat lineWidth = model.lineWidth;
|
|
|
- BOOL isDashed = model.style == CPDFBorderStyleDashed ? YES : NO;
|
|
|
- //绘制
|
|
|
- NSImage *image = [[NSImage alloc] initWithSize:CGSizeMake(maxX - minX, maxY - minY)];
|
|
|
- [image lockFocus];
|
|
|
-
|
|
|
- NSBezierPath *path = [NSBezierPath bezierPath];
|
|
|
- [path removeAllPoints];
|
|
|
-
|
|
|
- for (int i = 0; i < annotation.paths.count; i++) {
|
|
|
- NSArray *tempArray = annotation.paths[i];
|
|
|
- for (int j = 0; j < tempArray.count; j++) {
|
|
|
- CGPoint point = [tempArray[j] pointValue];
|
|
|
- if (i == 0 && j == 0) {
|
|
|
- [path moveToPoint:point];
|
|
|
- } else {
|
|
|
- [path lineToPoint:CGPointMake(point.x - minX, point.y - minY)];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (isDashed) {
|
|
|
- [path setLineDash:(CGFloat[]){5.0, 5.0} count:2 phase:0.0];
|
|
|
- }
|
|
|
- [color setStroke];
|
|
|
- [path setLineWidth: lineWidth];
|
|
|
- [path stroke];
|
|
|
-
|
|
|
- [image unlockFocus];
|
|
|
-
|
|
|
- CGImageRef cgImageRef = [image CGImageForProposedRect:NULL context:nil hints:nil];
|
|
|
- NSImage *finalImage = [[NSImage alloc] initWithCGImage:cgImageRef size:NSZeroSize];
|
|
|
- return finalImage;
|
|
|
-}
|
|
|
-
|
|
|
-@end
|