123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- //
- // KMDocumentAIPDFView.m
- // PDF Master
- //
- // Created by 丁林圭 on 2023/2/2.
- //
- #import "KMDocumentAIPDFView.h"
- #import "NSEvent+PDFListView.h"
- #import "NSGeometry+PDFListView.h"
- #import "KMDocumentAIPopViewController.h"
- #define DOCUMENT_SIZE 30.0
- @interface KMDocumentAIPDFView()<NSPopoverDelegate>
- //@property(nonatomic,retain) NSMutableArray<COCRResult *> * results;
- @property(nonatomic,assign) CGRect drawRecognitionEreaRect;
- @property(nonatomic,assign) CGRect recognitionEreaRect;
- @property (nonatomic, assign) NSUInteger selectionPageIndex;
- //@property (nonatomic, retain) COCRResult * activeResult;
- @property (nonatomic, assign) NSInteger activeResultIndex;
- @property (nonatomic, retain) CPDFPage * activeResultPage;
- @property (nonatomic, retain) NSPopover *popOver;
- @property (nonatomic, retain) KMDocumentAIPopViewController *documentAIPopViewController;
- @end
- @implementation KMDocumentAIPDFView
- - (NSPopover *)popOver {
- if(!_popOver) {
- _popOver = [[NSPopover alloc] init];
- _popOver.delegate = self;
- self.documentAIPopViewController = [[KMDocumentAIPopViewController alloc] initWithNibName:@"KMDocumentAIPopViewController" bundle:[NSBundle mainBundle]];
- _popOver.contentViewController = self.documentAIPopViewController;
- _popOver.animates = YES;
- __block typeof(self) blockSelf = self;
- self.documentAIPopViewController.callback = ^(NSInteger result) {
- if(result == 1) {
- // blockSelf.results[blockSelf.activeResultIndex].text = blockSelf.documentAIPopViewController.contentTextView.string?:@"";
- [blockSelf setNeedsDisplayAnnotationViewForPage:blockSelf.activeResultPage];
- }
- if(blockSelf.popOver.isShown)
- [blockSelf.popOver performClose:nil];
-
- };
- _popOver.behavior = NSPopoverBehaviorTransient;
- }
-
- return _popOver;
- }
- - (void)mouseDown:(NSEvent *)event {
- // if ([self doOCRResultWithEvent:event]) {
- // if(self.popOver.isShown) {
- // [self.popOver performClose:nil];
- // } else {
- // CGRect rect = [self convertRect:self.activeResult.textBounds fromPage:self.currentPage];
- // [self.popOver showRelativeToRect:rect ofView:self preferredEdge:NSRectEdgeMinY];
- // self.documentAIPopViewController.contentTextView.string = self.activeResult.text?:@"";
- // }
- // } else if ([self isRecognitionErea]) {
- // [self doSelectWithEvent:event];
- // }
- }
- //- (COCRResult *)doOCRResultWithEvent:(NSEvent *)theEvent {
- // COCRResult *result = nil;
- // NSPoint point = NSZeroPoint;
- // CPDFPage *page = [self pageAndPoint:&point forEvent:theEvent nearest:YES];
- //
- // for (NSInteger i = 0;i<self.results.count;i++) {
- // COCRResult *tResult = self.results[i];
- // if(CGRectContainsPoint(tResult.textBounds, point)){
- // result = tResult;
- // self.activeResultIndex = i;
- // break;
- // }
- // }
- // if(result) {
- // self.activeResult = result;
- // self.activeResultPage = page;
- // } else {
- // self.activeResult = nil;
- // self.activeResultPage = nil;
- // self.activeResultIndex = -1;
- // }
- //
- // return result;
- //}
- - (void)mouseMoved:(NSEvent *)event {
- }
- - (void)keyDown:(NSEvent *)event {
-
- }
- - (void)mouseExited:(NSEvent *)event {
- }
- - (NSRect)recognitionRect {
- return self.recognitionEreaRect;
- }
- - (void)clearOCRResult {
- self.resultDics = @[].mutableCopy;
- [self setNeedsDisplayAnnotationViewForPage:self.currentPage];
- }
- - (void)doSelectWithEvent:(NSEvent *)theEvent {
- NSPoint initialPoint = NSZeroPoint;
- CPDFPage *page = [self pageAndPoint:&initialPoint forEvent:theEvent nearest:NO];
-
- CGFloat margin = DOCUMENT_SIZE / [self scaleFactor];
-
- self.selectionPageIndex = [page pageIndex];
- BOOL didSelect = (NO == NSIsEmptyRect(self.recognitionEreaRect));
-
- CRectEdges resizeHandle = didSelect ? CPDFListViewResizeHandleForPointFromRect(initialPoint, self.recognitionEreaRect, margin) : 0;
-
- if (resizeHandle == 0 && (didSelect == NO || NSPointInRect(initialPoint, self.recognitionEreaRect) == NO)) {
- self.recognitionEreaRect = CGRectMake(initialPoint.x, initialPoint.y, 0, 0);
- resizeHandle = CMaxXEdgeMask | CMinYEdgeMask;
- if (didSelect)
- [self setNeedsDisplay:YES];
- }
-
- NSRect initialRect = self.recognitionEreaRect;
- NSRect pageBounds = [page boundsForBox:[self displayBox]];
- CRectEdges newEffectiveResizeHandle, effectiveResizeHandle = resizeHandle;
-
- [self setCursorForAreaOfInterest:CAreaOfInterestForResizeHandle(resizeHandle, page)];
- CGFloat mouseOffset = NSWidth([self convertRect:NSMakeRect(0.0, 0.0, 1.0, 1.0) toPage:page]);
- while (YES) {
- theEvent = [[self window] nextEventMatchingMask: NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged];
- if ([theEvent type] == NSEventTypeLeftMouseUp) {
- if (!NSIsEmptyRect(self.recognitionEreaRect)) {
- [NSMenu popUpContextMenu:[self menuForEvent:theEvent] withEvent:theEvent forView:self];
- }
- break;
- }
-
- CGPoint zPoint = initialPoint;
- [self pageAndPoint:&zPoint forEvent:theEvent nearest:YES];
- CGRect zRect = CGRectMake(initialPoint.x-2*mouseOffset, initialPoint.y-2*mouseOffset, 4*mouseOffset, 4*mouseOffset);
- if (CGRectContainsPoint(zRect, zPoint)) {continue;}
-
- NSPoint newPoint = CGPointZero;
- NSRect newRect = initialRect;
- NSPoint delta = CGPointZero;
-
- newPoint = [self convertPoint:[theEvent locationInPDFListView:self] toPage:page];
- delta = CPDFListViewSubstractPoints(newPoint, initialPoint);
-
- if (resizeHandle) {
- newEffectiveResizeHandle = 0;
- if ((resizeHandle & CMaxXEdgeMask))
- newEffectiveResizeHandle |= newPoint.x < NSMinX(initialRect) ? CMinXEdgeMask : CMaxXEdgeMask;
- else if ((resizeHandle & CMinXEdgeMask))
- newEffectiveResizeHandle |= newPoint.x > NSMaxX(initialRect) ? CMaxXEdgeMask : CMinXEdgeMask;
- if ((resizeHandle & CMaxYEdgeMask))
- newEffectiveResizeHandle |= newPoint.y < NSMinY(initialRect) ? CMinYEdgeMask : CMaxYEdgeMask;
- else if ((resizeHandle & CMinYEdgeMask))
- newEffectiveResizeHandle |= newPoint.y > NSMaxY(initialRect) ? CMaxYEdgeMask : CMinYEdgeMask;
- if (newEffectiveResizeHandle != effectiveResizeHandle) {
- effectiveResizeHandle = newEffectiveResizeHandle;
- [self setCursorForAreaOfInterest:CAreaOfInterestForResizeHandle(effectiveResizeHandle, page)];
- }
- }
-
- if (resizeHandle == CEditInEdgeMask) {
- newRect.origin = CPDFListViewAddPoints(newRect.origin, delta);
- } else if (([theEvent modifierFlags] & NSEventModifierFlagShift)) {
- CGFloat width = NSWidth(newRect);
- CGFloat height = NSHeight(newRect);
- CGFloat square;
-
- if ((resizeHandle & CMaxXEdgeMask))
- width += delta.x;
- else if ((resizeHandle & CMinXEdgeMask))
- width -= delta.x;
- if ((resizeHandle & CMaxYEdgeMask))
- height += delta.y;
- else if ((resizeHandle & CMinYEdgeMask))
- height -= delta.y;
-
- if (0 == (resizeHandle & (CMinXEdgeMask | CMaxXEdgeMask)))
- square = fabs(height);
- else if (0 == (resizeHandle & (CMinYEdgeMask | CMaxYEdgeMask)))
- square = fabs(width);
- else
- square = fmax(fabs(width), fabs(height));
-
- if ((resizeHandle & CMinXEdgeMask)) {
- if (width >= 0.0 && NSMaxX(newRect) - square < NSMinX(pageBounds))
- square = NSMaxX(newRect) - NSMinX(pageBounds);
- else if (width < 0.0 && NSMaxX(newRect) + square > NSMaxX(pageBounds))
- square = NSMaxX(pageBounds) - NSMaxX(newRect);
- } else {
- if (width >= 0.0 && NSMinX(newRect) + square > NSMaxX(pageBounds))
- square = NSMaxX(pageBounds) - NSMinX(newRect);
- else if (width < 0.0 && NSMinX(newRect) - square < NSMinX(pageBounds))
- square = NSMinX(newRect) - NSMinX(pageBounds);
- }
- if ((resizeHandle & CMinYEdgeMask)) {
- if (height >= 0.0 && NSMaxY(newRect) - square < NSMinY(pageBounds))
- square = NSMaxY(newRect) - NSMinY(pageBounds);
- else if (height < 0.0 && NSMaxY(newRect) + square > NSMaxY(pageBounds))
- square = NSMaxY(pageBounds) - NSMaxY(newRect);
- } else {
- if (height >= 0.0 && NSMinY(newRect) + square > NSMaxY(pageBounds))
- square = NSMaxY(pageBounds) - NSMinY(newRect);
- if (height < 0.0 && NSMinY(newRect) - square < NSMinY(pageBounds))
- square = NSMinY(newRect) - NSMinY(pageBounds);
- }
-
- if ((resizeHandle & CMinXEdgeMask))
- newRect.origin.x = width < 0.0 ? NSMaxX(newRect) : NSMaxX(newRect) - square;
- else if (width < 0.0 && (resizeHandle & CMaxXEdgeMask))
- newRect.origin.x = NSMinX(newRect) - square;
- if ((resizeHandle & CMinYEdgeMask))
- newRect.origin.y = height < 0.0 ? NSMaxY(newRect) : NSMaxY(newRect) - square;
- else if (height < 0.0 && (resizeHandle & CMaxYEdgeMask))
- newRect.origin.y = NSMinY(newRect) - square;
- newRect.size.width = newRect.size.height = square;
- } else {
- if ((resizeHandle & CMaxXEdgeMask)) {
- newRect.size.width += delta.x;
- if (NSWidth(newRect) < 0.0) {
- newRect.size.width *= -1.0;
- newRect.origin.x -= NSWidth(newRect);
- }
- } else if ((resizeHandle & CMinXEdgeMask)) {
- newRect.origin.x += delta.x;
- newRect.size.width -= delta.x;
- if (NSWidth(newRect) < 0.0) {
- newRect.size.width *= -1.0;
- newRect.origin.x -= NSWidth(newRect);
- }
- }
-
- if ((resizeHandle & CMaxYEdgeMask)) {
- newRect.size.height += delta.y;
- if (NSHeight(newRect) < 0.0) {
- newRect.size.height *= -1.0;
- newRect.origin.y -= NSHeight(newRect);
- }
- } else if ((resizeHandle & CMinYEdgeMask)) {
- newRect.origin.y += delta.y;
- newRect.size.height -= delta.y;
- if (NSHeight(newRect) < 0.0) {
- newRect.size.height *= -1.0;
- newRect.origin.y -= NSHeight(newRect);
- }
- }
- }
-
- newRect = CPDFListViewIntersectionRect(newRect, pageBounds);
- if (didSelect) {
- NSRect dirtyRect = NSUnionRect(NSInsetRect(self.recognitionEreaRect, -margin, -margin), NSInsetRect(newRect, -margin, -margin));
- [self setNeedsDisplayAnnotationInRect:dirtyRect];
- } else {
- [self setNeedsDisplayAnnotationViewForVisiblePages];
- didSelect = YES;
- }
- @synchronized (self) {
- self.recognitionEreaRect = newRect;
- }
- }
-
- if (NSIsEmptyRect(self.recognitionEreaRect)) {
- @synchronized (self) {
- self.recognitionEreaRect = NSZeroRect;
- self.selectionPageIndex = NSNotFound;
- }
-
- [self setNeedsDisplay:YES];
- } else if (resizeHandle) {
- [self setNeedsDisplayAnnotationInRect:NSInsetRect(self.recognitionEreaRect, -margin, -margin)];
- }
- }
- - (CPDFPage *)pageAndPoint:(NSPoint *)point forEvent:(NSEvent *)event nearest:(BOOL)nearest {
- NSPoint p = [event locationInPDFListView:self];
- CPDFPage *page = [self pageForPoint:p nearest:nearest];
- if (page && point)
- *point = [self convertPoint:p toPage:page];
- return page;
- }
- //- (void)updateResult:(NSArray<COCRResult *> *)results recognitionRect:(CGRect)recognitionRect {
- // self.results = [NSMutableArray arrayWithArray:results];
- // self.drawRecognitionEreaRect = recognitionRect;
- // [self setNeedsDisplayAnnotationViewForPage:self.currentPage];
- //}
- //
- //- (void)drawPage:(CPDFPage *)page toContext:(CGContextRef)context {
- // if(self.resultDics.count > 0) {
- // NSInteger currentIndex = [self.document indexForPage:page];
- // NSArray<COCRResult *> *currentResults = @[];
- // for (NSDictionary *dic in self.resultDics) {
- // if(dic[@"page"] && [dic[@"page"] integerValue] == currentIndex) {
- // if(dic[@"results"]) {
- // currentResults = dic[@"results"];
- // break;
- // }
- // }
- // }
- // if (currentResults.count>0) {
- // [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:context flipped:NO]];
- //
- // CGContextSaveGState(context);
- // CGContextAddRect(context, self.drawRecognitionEreaRect);
- // CGContextSetRGBFillColor(context, 1, 1, 1, 0.7);
- // CGContextFillPath(context);
- // CGContextRestoreGState(context);
- //
- // NSMutableDictionary *dic = [NSMutableDictionary dictionary];
- // [dic setValue:[NSColor blackColor] forKey:NSForegroundColorAttributeName];
- //
- // for (COCRResult * cOcrResult in currentResults) {
- // CGContextSaveGState(context);
- //
- // CGRect rect = cOcrResult.textBounds;
- //
- // NSString *strChar = cOcrResult.text;
- // CGFloat fontsize = 1.0;
- // NSFont *font = [NSFont systemFontOfSize:fontsize];
- // CGSize strSize = [strChar sizeWithAttributes:@{NSFontAttributeName:font}];
- // while ((fontsize<127) && !(strSize.width>=cOcrResult.textBounds.size.width || strSize.height>=cOcrResult.textBounds.size.height)) {
- // fontsize += 1.0;
- // font = [NSFont systemFontOfSize:fontsize];
- // strSize = [strChar sizeWithAttributes:@{NSFontAttributeName:font}];
- // }
- // NSFont *drawFont = [NSFont systemFontOfSize:fontsize-1];
- //
- // strSize = [strChar sizeWithAttributes:@{NSFontAttributeName:drawFont}];
- // CGFloat k = (cOcrResult.textBounds.size.width - strSize.width)/(strChar.length);
- //
- // NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
- //
- // NSDictionary *attriDict = @{NSParagraphStyleAttributeName:style,NSKernAttributeName:@(k),NSFontAttributeName:drawFont};
- //
- // NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:strChar attributes:attriDict];
- // [attributeString drawInRect:rect];
- //
- // CGContextAddRect(context, rect);
- // CGContextSetLineWidth(context, 1.0);
- // CGContextSetStrokeColorWithColor(context, [NSColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1.0].CGColor);
- // CGContextStrokePath(context);
- //
- // CGContextRestoreGState(context);
- // }
- // }
- //
- // }
- //
- // if(!CGRectEqualToRect(self.recognitionEreaRect, CGRectZero)) {
- // @synchronized (self) {
- // CGContextSaveGState(context);
- //
- // CGFloat size = DOCUMENT_SIZE;
- // CGContextSetLineWidth(context, 5.0);
- // CGContextSetStrokeColorWithColor(context, [NSColor colorWithRed:23.0/255.0 green:112.0/255.0 blue:244.0/255.0 alpha:1.0].CGColor);
- //
- // CGContextMoveToPoint(context, CGRectGetMidX(self.recognitionEreaRect)-size/2, CGRectGetMaxY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMidX(self.recognitionEreaRect)+size/2, CGRectGetMaxY(self.recognitionEreaRect));
- //
- // CGContextMoveToPoint(context, CGRectGetMidX(self.recognitionEreaRect)-size/2, CGRectGetMinY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMidX(self.recognitionEreaRect)+size/2, CGRectGetMinY(self.recognitionEreaRect));
- //
- // CGContextMoveToPoint(context, CGRectGetMinX(self.recognitionEreaRect), CGRectGetMidY(self.recognitionEreaRect)-size/2);
- // CGContextAddLineToPoint(context, CGRectGetMinX(self.recognitionEreaRect), CGRectGetMidY(self.recognitionEreaRect)+size/2);
- //
- // CGContextMoveToPoint(context, CGRectGetMaxX(self.recognitionEreaRect), CGRectGetMidY(self.recognitionEreaRect)-size/2);
- // CGContextAddLineToPoint(context, CGRectGetMaxX(self.recognitionEreaRect), CGRectGetMidY(self.recognitionEreaRect)+size/2);
- //
- // CGContextMoveToPoint(context, CGRectGetMaxX(self.recognitionEreaRect)-size/2, CGRectGetMinY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMaxX(self.recognitionEreaRect), CGRectGetMinY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMaxX(self.recognitionEreaRect), CGRectGetMinY(self.recognitionEreaRect)+ size/2);
- //
- // CGContextMoveToPoint(context, CGRectGetMinX(self.recognitionEreaRect)+size/2, CGRectGetMinY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMinX(self.recognitionEreaRect), CGRectGetMinY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMinX(self.recognitionEreaRect), CGRectGetMinY(self.recognitionEreaRect)+ size/2);
- //
- // CGContextMoveToPoint(context, CGRectGetMinX(self.recognitionEreaRect)+size/2, CGRectGetMaxY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMinX(self.recognitionEreaRect), CGRectGetMaxY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMinX(self.recognitionEreaRect), CGRectGetMaxY(self.recognitionEreaRect) - size/2);
- //
- // CGContextMoveToPoint(context, CGRectGetMaxX(self.recognitionEreaRect)-size/2, CGRectGetMaxY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMaxX(self.recognitionEreaRect), CGRectGetMaxY(self.recognitionEreaRect));
- // CGContextAddLineToPoint(context, CGRectGetMaxX(self.recognitionEreaRect), CGRectGetMaxY(self.recognitionEreaRect) - size/2);
- //
- // CGContextStrokePath(context);
- //
- // CGContextSetLineCap(context, kCGLineCapRound);
- // CGContextSetLineWidth(context, 2.0);
- // CGContextRestoreGState(context);
- //
- // CGContextSetStrokeColorWithColor(context, [NSColor colorWithRed:23.0/255.0 green:112.0/255.0 blue:244.0/255.0 alpha:1.0].CGColor);
- // CGContextBeginPath(context);
- // CGContextMoveToPoint(context, self.recognitionEreaRect.origin.x, self.recognitionEreaRect.origin.y);
- // CGContextAddLineToPoint(context, self.recognitionEreaRect.origin.x+ self.recognitionEreaRect.size.width,self.recognitionEreaRect.origin.y);
- // CGContextAddLineToPoint(context, self.recognitionEreaRect.origin.x + self.recognitionEreaRect.size.width,self.recognitionEreaRect.origin.y + + self.recognitionEreaRect.size.height);
- // CGContextAddLineToPoint(context, self.recognitionEreaRect.origin.x,self.recognitionEreaRect.origin.y + + self.recognitionEreaRect.size.height);
- // CGContextClosePath(context);
- // CGFloat lengths[] = {10,5};
- // CGContextSetLineDash(context, 0, lengths,2);
- // CGContextStrokePath(context);
- // }
- // }
- //}
- #pragma Mark - menuForEvent
- -(NSMenu *)menuForEvent:(NSEvent *)event {
- NSMenu *menu = [[NSMenu alloc]init];
- if(self.isRecognitionErea && !NSEqualRects(NSZeroRect, self.recognitionEreaRect)) {
- NSMenuItem * sureMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Start OCR text recognition", nil) action:@selector(menuItemClick_StartOCR:) keyEquivalent:@""];
- [menu addItem:sureMenuItem];
- }
- return menu;
- }
- -(void)menuItemClick_StartOCR:(NSMenuItem *)item {
- if (self.callback) {
- self.callback(self.recognitionEreaRect,self.currentPage);
- }
-
- self.recognitionEreaRect = CGRectZero;
- [self setNeedsDisplayAnnotationViewForPage:self.currentPage];
- }
- @end
|