|
@@ -106,6 +106,175 @@ CGFloat DEFAULT_SNAPSHOT_HEIGHT = 200.0;
|
|
|
return annotation;
|
|
|
}
|
|
|
|
|
|
+- (void)addAnnotationWithImage:(NSImage *)image isRemoveBGColor:(BOOL)isRemoveBGColor {
|
|
|
+ // First try the current mouse position
|
|
|
+ NSPoint center = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil];
|
|
|
+ [self addAnnotationWithImage:image center:center isRemoveBGColor:isRemoveBGColor];
|
|
|
+}
|
|
|
+
|
|
|
+- (void)addAnnotationWithImage:(NSImage *)image center:(NSPoint)center isRemoveBGColor:(BOOL)isRemoveBGColor {
|
|
|
+ [self setToolMode:CTextToolMode]; //不支持重复添加,重置状态
|
|
|
+
|
|
|
+ if (isRemoveBGColor) {
|
|
|
+ NSData *imageData = [image TIFFRepresentation];
|
|
|
+ CGImageRef imageRef;
|
|
|
+ if (imageData) {
|
|
|
+ CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
|
|
|
+ imageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
|
|
|
+ } else {
|
|
|
+ return NSBeep();
|
|
|
+ }
|
|
|
+
|
|
|
+ const int imageWidth = image.size.width;
|
|
|
+ const int imageHeight = image.size.height;
|
|
|
+ size_t bytesPerRow = imageWidth * 4;
|
|
|
+ uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);
|
|
|
+
|
|
|
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
|
+ CGContextRef context = CGBitmapContextCreate(rgbImageBuf,
|
|
|
+ imageWidth,
|
|
|
+ imageHeight,
|
|
|
+ 8,
|
|
|
+ bytesPerRow,
|
|
|
+ colorSpace,
|
|
|
+ kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
|
|
|
+ CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), imageRef);
|
|
|
+
|
|
|
+ int pixelNum = imageWidth * imageHeight;
|
|
|
+ uint32_t* pCurPtr = rgbImageBuf;
|
|
|
+ for (int i = 0; i < pixelNum; i++, pCurPtr++) {
|
|
|
+ uint8_t* ptr = (uint8_t*)pCurPtr;
|
|
|
+ if (ptr[1] > 240 && ptr[2] > 240 && ptr[3] > 240) {
|
|
|
+ ptr[0] = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, nil);
|
|
|
+ imageRef = CGImageCreate(imageWidth,
|
|
|
+ imageHeight,
|
|
|
+ 8,
|
|
|
+ 32,
|
|
|
+ bytesPerRow,
|
|
|
+ colorSpace,
|
|
|
+ kCGImageAlphaLast |kCGBitmapByteOrder32Little,
|
|
|
+ dataProvider,
|
|
|
+ NULL,
|
|
|
+ true,
|
|
|
+ kCGRenderingIntentDefault);
|
|
|
+ CGDataProviderRelease(dataProvider);
|
|
|
+
|
|
|
+ NSImage *newImage = nil;
|
|
|
+ if (imageRef) {
|
|
|
+ NSRect imageRect = NSMakeRect(0.0, 0.0, 0.0, 0.0);
|
|
|
+ CGContextRef imageContext = nil;
|
|
|
+
|
|
|
+ // Get the image dimensions.
|
|
|
+ imageRect.size.height = CGImageGetHeight(imageRef);
|
|
|
+ imageRect.size.width = CGImageGetWidth(imageRef);
|
|
|
+
|
|
|
+ // Create a new image to receive the Quartz image data.
|
|
|
+ newImage = [[NSImage alloc] initWithSize:imageRect.size];
|
|
|
+ [newImage lockFocus];
|
|
|
+
|
|
|
+ // Get the Quartz context and draw.
|
|
|
+ imageContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
|
|
+ CGContextDrawImage(imageContext, *(CGRect*)&imageRect, imageRef);
|
|
|
+ [newImage unlockFocus];
|
|
|
+ CGImageRelease(imageRef);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (newImage) {
|
|
|
+ [self addAnnotationWithImage:newImage center:center];
|
|
|
+ } else {
|
|
|
+ [self addAnnotationWithImage:image center:center];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ [self addAnnotationWithImage:image center:center];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+- (void)addAnnotationWithImage:(NSImage *)image center:(NSPoint)center {
|
|
|
+ CPDFPage *page = nil;
|
|
|
+ NSRect bounds = NSZeroRect;
|
|
|
+ CPDFSelection *selection = [self currentSelection];
|
|
|
+ page = [selection safeFirstPage];
|
|
|
+
|
|
|
+ // if the mouse was in the toolbar and there is a page below the toolbar, we get a point outside of the visible rect
|
|
|
+ page = NSMouseInRect(center, [self visibleContentRect], [self isFlipped]) ? [self pageForPoint:center nearest:NO] : nil;
|
|
|
+
|
|
|
+ if (page == nil) {
|
|
|
+ // Get center of the PDFView.
|
|
|
+ NSRect viewFrame = [self frame];
|
|
|
+ center = NSMakePoint(NSMidX(viewFrame), NSMidY(viewFrame));
|
|
|
+ page = [self pageForPoint: center nearest: YES];
|
|
|
+ if (page == nil) {
|
|
|
+ // Get center of the current page
|
|
|
+ page = [self currentPage];
|
|
|
+ center = [self convertPoint:NSMakePoint(NSMidX([page boundsForBox:[self displayBox]]), NSMidY([page boundsForBox:[self displayBox]])) fromPage:page];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ CGFloat defaultWidth = 360;
|
|
|
+ CGFloat defaultHeight = 90;
|
|
|
+ NSSize defaultSize = ([page rotation] % 180 == 0) ? NSMakeSize(defaultWidth, defaultHeight) : NSMakeSize(defaultHeight, defaultWidth);
|
|
|
+
|
|
|
+ // Convert to "page space".
|
|
|
+ center = NSMakePoint(round([self convertPoint: center toPage: page].x), round([self convertPoint: center toPage: page].y));
|
|
|
+ NSRect rect;
|
|
|
+ rect.origin.x = center.x - 0.5 * defaultSize.width;
|
|
|
+ rect.origin.y = center.y - 0.5 * defaultSize.height;
|
|
|
+ rect.size = defaultSize;
|
|
|
+ bounds = rect;
|
|
|
+
|
|
|
+ // Make sure it fits in the page
|
|
|
+ if (NSWidth(bounds) > NSWidth([page boundsForBox:[self displayBox]]))
|
|
|
+ bounds.size.width = NSWidth([page boundsForBox:[self displayBox]]);
|
|
|
+ if (NSHeight(bounds) > NSHeight([page boundsForBox:[self displayBox]]))
|
|
|
+ bounds.size.height = NSHeight([page boundsForBox:[self displayBox]]);
|
|
|
+
|
|
|
+ if (NSMinX(bounds) < NSMinX([page boundsForBox:[self displayBox]]))
|
|
|
+ bounds.origin.x = NSMinX([page boundsForBox:[self displayBox]]);
|
|
|
+ else if (NSMaxX(bounds) > NSMaxX([page boundsForBox:[self displayBox]]))
|
|
|
+ bounds.origin.x = NSMaxX([page boundsForBox:[self displayBox]]) - NSWidth(bounds);
|
|
|
+
|
|
|
+ if (NSMinY(bounds) < NSMinY([page boundsForBox:[self displayBox]]))
|
|
|
+ bounds.origin.y = NSMinY([page boundsForBox:[self displayBox]]);
|
|
|
+ else if (NSMaxY(bounds) > NSMaxY([page boundsForBox:[self displayBox]]))
|
|
|
+ bounds.origin.y = NSMaxY([page boundsForBox:[self displayBox]]) - NSHeight(bounds);
|
|
|
+
|
|
|
+ if (page != nil) {
|
|
|
+ BOOL isInitial = NSEqualSizes(bounds.size, NSZeroSize) && selection == nil;
|
|
|
+ NSRect pageBounds = [page boundsForBox:CPDFDisplayMediaBox];
|
|
|
+
|
|
|
+ // new note added by note tool mode, don't add actual zero sized notes
|
|
|
+ if (isInitial)
|
|
|
+ bounds = SKRectFromCenterAndSquareSize(bounds.origin, 8.0);
|
|
|
+
|
|
|
+ if(!CGPointEqualToPoint(self.lastAddAnnotationPoint, CGPointZero)) {
|
|
|
+ bounds.origin.x = self.lastAddAnnotationPoint.x + 3.0;
|
|
|
+ bounds.origin.y = self.lastAddAnnotationPoint.y - 3.0;
|
|
|
+ CGFloat pageWidth = pageBounds.size.width;
|
|
|
+
|
|
|
+ if (bounds.origin.x + bounds.size.width >pageWidth) {
|
|
|
+ bounds.origin.x = pageWidth - bounds.size.width;
|
|
|
+ }
|
|
|
+ if (bounds.origin.y - bounds.size.height < 0) {
|
|
|
+ bounds.origin.y = bounds.size.height;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ self.lastAddAnnotationPoint = bounds.origin;
|
|
|
+
|
|
|
+ KMAnnotationStamp *newAnnotation = [[KMAnnotationStamp alloc] initWithBounds:bounds];
|
|
|
+// newAnnotation.image = image;
|
|
|
+
|
|
|
+ [newAnnotation registerUserName];
|
|
|
+ [self addAnnotation:newAnnotation toPage:page];
|
|
|
+ [[self undoManager] setActionName:NSLocalizedString(@"Add Note", @"Undo action name")];
|
|
|
+
|
|
|
+ [self setActiveAnnotations:@[newAnnotation]];
|
|
|
+ } else NSBeep();
|
|
|
+}
|
|
|
+
|
|
|
- (void)addAnnotationWithStamp:(KMAnnotationStamp *)stamp {
|
|
|
// First try the current mouse position
|
|
|
NSPoint center = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil];
|