KMRedactPDFView.swift 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. //
  2. // KMRedactPDFView.swift
  3. // PDF Master
  4. //
  5. // Created by tangchao on 2023/12/18.
  6. //
  7. import Cocoa
  8. class KMRedactPDFView: CPDFView {
  9. /*
  10. typedef enum {
  11. KMPDFRedactViewOperationTypeNone,//没有进入任何模式
  12. KMPDFRedactViewOperationTypeRedact,//标记密文模式
  13. KMPDFRedactViewOperationTypeEidtText,//文本编辑
  14. }KMPDFRedactViewOperationType;
  15. @interface KMRedactPDFView : CPDFView
  16. @property (nonatomic,retain) CPDFAnnotation *mouseMoveAnnotation;
  17. @property (nonatomic,retain) CPDFRedactAnnotation *currentAnnotation;
  18. @property (nonatomic,retain) NSMutableArray *newAddAnnotation;
  19. @property (nonatomic,retain) NSMutableArray *activeAnnotations;
  20. @property (nonatomic,assign) KMPDFRedactViewOperationType operationType;
  21. @property (nonatomic,assign) BOOL isEidtImageModel;
  22. @property (nonatomic,assign) BOOL isEidtTextModel;
  23. @property (nonatomic, copy) void(^eventColorChanged)(NSColor *color);
  24. @property (nonatomic, copy) void(^eventFontChanged)(void);
  25. @property (nonatomic, copy) void(^exportBtnTaped)(NSInteger type);
  26. - (void)resignMonitor;
  27. */
  28. /*
  29. @property (nonatomic, retain) id localMonitor;
  30. */
  31. override func draw(_ dirtyRect: NSRect) {
  32. super.draw(dirtyRect)
  33. // Drawing code here.
  34. }
  35. /*
  36. - (void)dealloc {
  37. [_currentAnnotation release];
  38. [_mouseMoveAnnotation release];
  39. [_newAddAnnotation release];
  40. [_activeAnnotations release];
  41. [_localMonitor release];
  42. Block_release(_eventColorChanged);
  43. Block_release(_eventFontChanged);
  44. [super dealloc];
  45. }
  46. - (id)initWithFrame:(NSRect)frameRect {
  47. self = [super initWithFrame:frameRect];
  48. if (self) {
  49. self.operationType = KMPDFRedactViewOperationTypeNone;
  50. [self addTrackingArea];
  51. [self initMonitor];
  52. }
  53. return self;
  54. }
  55. - (id)initWithCoder:(NSCoder *)decoder {
  56. self = [super initWithCoder:decoder];
  57. if (self) {
  58. self.operationType = KMPDFRedactViewOperationTypeNone;
  59. [self addTrackingArea];
  60. [self initMonitor];
  61. }
  62. return self;
  63. }
  64. - (void)addTrackingArea
  65. {
  66. self.newAddAnnotation = [NSMutableArray array];
  67. self.activeAnnotations = [NSMutableArray array];
  68. NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingMouseEnteredAndExited | NSTrackingInVisibleRect | NSTrackingActiveInKeyWindow | NSTrackingMouseMoved owner:self userInfo:nil];
  69. [self addTrackingArea:trackingArea];
  70. [trackingArea release];
  71. }
  72. - (void)initMonitor {
  73. NSEventMask mask = NSEventMaskKeyDown;
  74. if (!_localMonitor) {
  75. _localMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:mask handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) {
  76. unichar eventChar = [event firstCharacter];
  77. NSUInteger modifiers = [event standardModifierFlags];
  78. if ((eventChar == NSDeleteCharacter || eventChar == NSDeleteFunctionKey) &&
  79. (modifiers == 0)) {
  80. [self delete];
  81. }
  82. if ([event keyCode] == 36 && modifiers == 0) {
  83. [self corpImageDoneWithEnter];
  84. }
  85. return event;
  86. }];
  87. }
  88. }
  89. //注销检测器
  90. - (void)resignMonitor
  91. {
  92. [NSEvent removeMonitor:_localMonitor];
  93. _localMonitor = nil;
  94. }
  95. - (CGSize)getWidthFromText:(NSString *)text WithSize:(NSFont *)font AboutWidth:(CGFloat)width AndHeight:(CGFloat)height
  96. {
  97. if (!text) {
  98. return CGSizeMake(0, 0);
  99. }
  100. CGRect rect = [text boundingRectWithSize:CGSizeMake(width, height) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:font} context:nil];
  101. return rect.size;
  102. }
  103. - (NSMenu *)menuForEvent:(NSEvent *)event {
  104. NSMenu *menu = [super menuForEvent:event];
  105. if (!menu) {
  106. menu = [[[NSMenu alloc] init] autorelease];
  107. }
  108. NSPoint pagePoint = NSZeroPoint;
  109. CPDFPage *page = [self pageAndPoint:&pagePoint forEvent:event nearest:YES];
  110. CPDFAnnotation *annotation = [page annotationAtPoint:pagePoint];
  111. if(annotation && [annotation isKindOfClass:[CPDFRedactAnnotation class]] && self.operationType == KMPDFRedactViewOperationTypeRedact) {
  112. NSMenuItem *item = [menu insertItemWithTitle:NSLocalizedString(@"Delete", nil) action:@selector(deleteAnnotation:) target:self atIndex:0];
  113. [item setRepresentedObject:annotation];
  114. [menu insertItem:[NSMenuItem separatorItem] atIndex:1];
  115. NSMenuItem *itemDefault = [menu insertItemWithTitle:NSLocalizedString(@"Make Current Properties Default", nil) action:@selector(setPropertiesDefault:) target:self atIndex:2];
  116. [itemDefault setRepresentedObject:annotation];
  117. [menu insertItemWithTitle:NSLocalizedString(@"Properties...", nil) action:@selector(properties:) target:self atIndex:3];
  118. [menu insertItem:[NSMenuItem separatorItem] atIndex:4];
  119. [menu insertItemWithTitle:NSLocalizedString(@"Repeat Mark Across Pages", nil) action:@selector(repeatMark:) target:self atIndex:5];
  120. [menu insertItemWithTitle:NSLocalizedString(@"Apply Redactions", nil) action:@selector(applyRedact:) target:self atIndex:6];
  121. self.currentAnnotation = (CPDFRedactAnnotation *)annotation;
  122. }
  123. return menu;
  124. }
  125. #pragma mark Menu validation
  126. - (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
  127. if (!self.document || [self.document isLocked]) {
  128. return NO;
  129. }
  130. SEL action = [menuItem action];
  131. if (action == @selector(deleteAnnotation:)) {
  132. return YES;
  133. } else if (action == @selector(setPropertiesDefault:)) {
  134. return YES;
  135. } else if (action == @selector(properties:)) {
  136. return YES;
  137. } else if (action == @selector(repeatMark:)) {
  138. if(self.document.pageCount == 1)
  139. return NO;
  140. return YES;
  141. } else if (action == @selector(applyRedact:)) {
  142. return YES;
  143. } else {
  144. return [super validateMenuItem:menuItem];
  145. }
  146. }
  147. - (NSArray<NSMenuItem *> *)menuItemsEditingAtPoint:(CGPoint)point forPage:(CPDFPage *)page {
  148. NSMutableArray <NSMenuItem *>*menuItems = [super menuItemsEditingAtPoint:point forPage:page].mutableCopy;
  149. if (!menuItems) {
  150. menuItems = [NSMutableArray array];
  151. }
  152. if ([self isSelectEditCharRange] || [self isSelecteditAreaWithPoint:point]) {
  153. [menuItems insertObject:[NSMenuItem separatorItem] atIndex:0];
  154. [menuItems insertObject:[self fontColorMenuItem] atIndex:0];
  155. [menuItems insertObject:[self fontSizeMenuItem] atIndex:0];
  156. }
  157. if (self.editingArea) {
  158. if (self.editingArea.IsImageArea) {
  159. [menuItems insertObject:[NSMenuItem separatorItem] atIndex:0];
  160. // [menuItems insertObject:[self imageCutMenuItem] atIndex:0];
  161. // [menuItems insertObject:[self imagePasteMenuItem] atIndex:0];
  162. [menuItems insertObject:[self imageExportMenuItem] atIndex:0];
  163. [menuItems insertObject:[self imageRotateMenuItem] atIndex:0];
  164. }
  165. }
  166. return menuItems;
  167. }
  168. - (void)mouseMoved:(NSEvent *)theEvent {
  169. [self.window mouseMoved:theEvent];
  170. [super mouseMoved:theEvent];
  171. if(self.operationType != KMPDFRedactViewOperationTypeRedact) return;
  172. NSPoint pagePoint = NSZeroPoint;
  173. CPDFPage *page = [self pageAndPoint:&pagePoint forEvent:theEvent nearest:YES];
  174. NSPoint newpoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
  175. CPDFAreaOfInterest area = [self areaOfInterestForPoint:newpoint];
  176. if (area & CPDFTextArea) {
  177. [[NSCursor IBeamCursor] set];
  178. }else{
  179. [[NSCursor arrowCursor] set];
  180. }
  181. CPDFAnnotation *newActiveAnnotation = [page annotationAtPoint:pagePoint];
  182. if (newActiveAnnotation && [newActiveAnnotation isKindOfClass:[CPDFRedactAnnotation class]] && (self.mouseMoveAnnotation == newActiveAnnotation)) {
  183. [(CPDFRedactAnnotation *)newActiveAnnotation setDrawRedactionsAsRedacted:YES];
  184. [self setNeedsDisplayAnnotationViewForPage:page];
  185. } else if(self.mouseMoveAnnotation && [self.mouseMoveAnnotation isKindOfClass:[CPDFRedactAnnotation class]]){
  186. [(CPDFRedactAnnotation *)self.mouseMoveAnnotation setDrawRedactionsAsRedacted:NO];
  187. [self setNeedsDisplayAnnotationViewForPage:page];
  188. }
  189. self.mouseMoveAnnotation = newActiveAnnotation;
  190. }
  191. - (void)mouseDown:(NSEvent *)theEvent {
  192. NSPoint pagePoint = NSZeroPoint;
  193. if(self.operationType != KMPDFRedactViewOperationTypeRedact) return;
  194. CPDFPage *page = [self pageAndPoint:&pagePoint forEvent:theEvent nearest:YES];
  195. CPDFAnnotation *newActiveAnnotation = [page annotationAtPoint:pagePoint];
  196. NSPoint newpoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
  197. CPDFAreaOfInterest area = [self areaOfInterestForPoint:newpoint];
  198. [self.activeAnnotations removeAllObjects]; //预留
  199. if(newActiveAnnotation) {
  200. if(![self.activeAnnotations containsObject:newActiveAnnotation]) {
  201. [self.activeAnnotations addObject:newActiveAnnotation];
  202. }
  203. [self setNeedsDisplayAnnotationViewForPage:page];
  204. [self doDragMouseWithEvent:theEvent];
  205. } else if(area & CPDFTextArea) {
  206. [super mouseDown:theEvent];
  207. [self doMarkUpWithEvent:theEvent];
  208. self.currentSelection = nil;
  209. } else {
  210. [self doRedactWithEvent:theEvent];
  211. }
  212. }
  213. #pragma mark - keyDown
  214. - (void)delete {
  215. [self.activeAnnotations enumerateObjectsUsingBlock:^(CPDFAnnotation * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  216. if([obj isKindOfClass:[CPDFRedactAnnotation class]]) {
  217. [self removeAnnotation:obj];
  218. }
  219. }];
  220. }
  221. - (void)corpImageDoneWithEnter {
  222. if([self.editingArea isKindOfClass:[CPDFEditImageArea class]]) {
  223. CPDFEditImageArea *editImageArea = (CPDFEditImageArea *)self.editingArea;
  224. if(editImageArea.isCropMode) {
  225. [self cropEditImageArea:editImageArea withBounds:editImageArea.cropRect];
  226. [self exitCropWithEditImageArea:editImageArea];
  227. }
  228. }
  229. }
  230. #pragma mark - Rendering
  231. - (void)drawPage:(CPDFPage *)page toContext:(CGContextRef)context
  232. {
  233. [self.activeAnnotations enumerateObjectsUsingBlock:^(CPDFAnnotation *annotation, NSUInteger idx, BOOL * _Nonnull stop) {
  234. if (annotation.page && [annotation.page isEqual:page]) {
  235. [annotation drawSelectionHighlightForView:self inContext:context];
  236. }
  237. }];
  238. }
  239. - (BOOL)doDragMouseWithEvent:(NSEvent *)theEvent
  240. {
  241. BOOL didDrag = NO;;
  242. while (YES) {
  243. if ([[[self window] nextEventMatchingMask: NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged] type] == NSEventTypeLeftMouseUp)
  244. break;
  245. didDrag = YES;
  246. }
  247. return didDrag;
  248. }
  249. - (void)doMarkUpWithEvent:(NSEvent *)theEvent
  250. {
  251. NSUInteger eventMask = NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged;
  252. while (YES) {
  253. theEvent = [[self window] nextEventMatchingMask:eventMask];
  254. if ([theEvent type] == NSEventTypeLeftMouseUp) {
  255. if (self.currentSelection) {
  256. CPDFPage *page = self.currentSelection.page;
  257. CPDFAnnotation *annotation = [self addRedactPDFSelection:self.currentSelection];
  258. [annotation setModificationDate:[NSDate date]];
  259. NSString *userName = [[NSUserDefaults standardUserDefaults] stringForKey:@"SKUserName"];
  260. [annotation setUserName:userName ? : NSFullUserName()];
  261. if ([annotation isKindOfClass:[CPDFRedactAnnotation class]]) {
  262. [annotation setBorderWidth:10];
  263. [(CPDFRedactAnnotation *)annotation setBorderColor:[KMPDFAnnotationRedactConfig sharedInstance].redactOutlineColor];
  264. [(CPDFRedactAnnotation *)annotation setInteriorColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFillColor];
  265. [(CPDFRedactAnnotation *)annotation setFontColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFontColor];
  266. if([KMPDFAnnotationRedactConfig sharedInstance].overlayText) {
  267. [(CPDFRedactAnnotation *)annotation setAlignment:[KMPDFAnnotationRedactConfig sharedInstance].textAlignment];
  268. NSFont* font = [NSFont fontWithName:@"Helvetica" size:[KMPDFAnnotationRedactConfig sharedInstance].fontSize];
  269. [(CPDFRedactAnnotation *)annotation setFont:font];
  270. [(CPDFRedactAnnotation *)annotation setOverlayText:[KMPDFAnnotationRedactConfig sharedInstance].overlayTextString];
  271. }
  272. }
  273. [self addAnnotation:annotation toPage:page];
  274. [self.newAddAnnotation addObject:annotation];
  275. [self setNeedsDisplayForPage:page];
  276. }
  277. break;
  278. } else if([theEvent type] == NSEventTypeLeftMouseDragged) {
  279. [super mouseDragged:theEvent];
  280. }
  281. }
  282. }
  283. - (void)doRedactWithEvent:(NSEvent *)theEvent
  284. {
  285. NSPoint point = NSZeroPoint;
  286. CPDFPage *page = [self pageAndPoint:&point forEvent:theEvent nearest:YES];
  287. BOOL wasMouseCoalescingEnabled = [NSEvent isMouseCoalescingEnabled];
  288. NSWindow *window = [self window];
  289. NSBezierPath *bezierPath = nil;
  290. CAShapeLayer *layer = nil;
  291. NSRect boxBounds = page.bounds;
  292. CGAffineTransform t = CGAffineTransformRotate(CGAffineTransformMakeScale([self scaleFactor], [self scaleFactor]), -M_PI_2 * [page rotation] / 90.0);
  293. layer = [CAShapeLayer layer];
  294. [layer setBounds:NSRectToCGRect(boxBounds)];
  295. [layer setAnchorPoint:CGPointZero];
  296. [layer setPosition:NSPointToCGPoint([self convertPoint:boxBounds.origin fromPage:page])];
  297. [layer setAffineTransform:t];
  298. [layer setZPosition:1.0];
  299. [layer setMasksToBounds:YES];
  300. [layer setFillColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFillColor.CGColor];
  301. [layer setStrokeColor:CGColorGetConstantColor(kCGColorBlack)];
  302. [layer setLineJoin:kCALineJoinRound];
  303. [layer setLineCap:kCALineCapRound];
  304. NSEvent *lastMouseEvent = theEvent;
  305. SKRectEdges resizeHandle = SKMinYEdgeMask | SKMaxXEdgeMask;
  306. CGRect originalBounds = CGRectMake(point.x, point.y, 0, 0);
  307. [[self layer] addSublayer:layer];
  308. NSUInteger eventMask = NSEventMaskLeftMouseUp | NSEventMaskLeftMouseDragged;
  309. CGRect rect = CGRectZero;
  310. while (YES) {
  311. theEvent = [window nextEventMatchingMask:eventMask];
  312. if ([theEvent type] == NSEventTypeLeftMouseUp) {
  313. if (rect.size.width < MIN_NOTE_SIZE || rect.size.height < MIN_NOTE_SIZE) {
  314. break;
  315. }
  316. NSMutableArray *quadrilateralPoints = [NSMutableArray array];
  317. CPDFRedactAnnotation *annotation = [[[CPDFRedactAnnotation alloc] initWithDocument:self.document] autorelease];
  318. CGRect bounds = rect;
  319. [quadrilateralPoints addObject:[NSValue valueWithPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds))]];
  320. [quadrilateralPoints addObject:[NSValue valueWithPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))]];
  321. [quadrilateralPoints addObject:[NSValue valueWithPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds))]];
  322. [quadrilateralPoints addObject:[NSValue valueWithPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds))]];
  323. [annotation setQuadrilateralPoints:quadrilateralPoints];
  324. [annotation setModificationDate:[NSDate date]];
  325. NSString *userName = [[NSUserDefaults standardUserDefaults] stringForKey:@"SKUserName"];
  326. [annotation setUserName:userName ? : NSFullUserName()];
  327. if ([annotation isKindOfClass:[CPDFRedactAnnotation class]]) {
  328. [annotation setBorderWidth:10];
  329. [(CPDFRedactAnnotation *)annotation setBorderColor:[KMPDFAnnotationRedactConfig sharedInstance].redactOutlineColor];
  330. [(CPDFRedactAnnotation *)annotation setInteriorColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFillColor];
  331. [(CPDFRedactAnnotation *)annotation setFontColor:[KMPDFAnnotationRedactConfig sharedInstance].redactFontColor];
  332. if([KMPDFAnnotationRedactConfig sharedInstance].overlayText) {
  333. [(CPDFRedactAnnotation *)annotation setAlignment:[KMPDFAnnotationRedactConfig sharedInstance].textAlignment];
  334. NSFont* font = [NSFont fontWithName:@"Helvetica" size:[KMPDFAnnotationRedactConfig sharedInstance].fontSize];
  335. [(CPDFRedactAnnotation *)annotation setFont:font];
  336. [(CPDFRedactAnnotation *)annotation setOverlayText:[KMPDFAnnotationRedactConfig sharedInstance].overlayTextString];
  337. }
  338. }
  339. [self addAnnotation:annotation toPage:page];
  340. [self.newAddAnnotation addObject:annotation];
  341. break;
  342. } else if ([theEvent type] == NSEventTypeLeftMouseDragged) {
  343. rect = [self doResizeLinkWithEvent:lastMouseEvent fromPoint:point originalBounds:originalBounds page:page resizeHandle:&resizeHandle];
  344. bezierPath = [NSBezierPath bezierPathWithRect:rect];
  345. [layer setPath:[bezierPath CGPath]];
  346. lastMouseEvent = theEvent;
  347. }
  348. }
  349. [layer removeFromSuperlayer];
  350. [NSEvent setMouseCoalescingEnabled:wasMouseCoalescingEnabled];
  351. }
  352. - (CPDFPage *)pageAndPoint:(NSPoint *)point forEvent:(NSEvent *)event nearest:(BOOL)nearest {
  353. NSPoint p = [event locationInView:self];
  354. CPDFPage *page = [self pageForPoint:p nearest:nearest];
  355. if (page && point)
  356. *point = [self convertPoint:p toPage:page];
  357. return page;
  358. }
  359. - (CGRect)doResizeLinkWithEvent:(NSEvent *)theEvent fromPoint:(NSPoint)originalPagePoint originalBounds:(NSRect)originalBounds page:(CPDFPage*)page resizeHandle:(SKRectEdges *)resizeHandlePtr
  360. {
  361. NSPoint currentPagePoint = [self convertPoint:[theEvent locationInView:self] toPage:page];
  362. NSRect newBounds = originalBounds;
  363. NSRect pageBounds = page.bounds;
  364. NSPoint relPoint = SKSubstractPoints(currentPagePoint, originalPagePoint);
  365. SKRectEdges resizeHandle = *resizeHandlePtr;
  366. if (NSEqualSizes(originalBounds.size, NSZeroSize)) {
  367. SKRectEdges currentResizeHandle = (relPoint.x < 0.0 ? SKMinXEdgeMask : SKMaxXEdgeMask) | (relPoint.y <= 0.0 ? SKMinYEdgeMask : SKMaxYEdgeMask);
  368. if (currentResizeHandle != resizeHandle) {
  369. *resizeHandlePtr = resizeHandle = currentResizeHandle;
  370. }
  371. }
  372. CGFloat minWidth = MIN_NOTE_SIZE;
  373. CGFloat minHeight = MIN_NOTE_SIZE;
  374. if ((resizeHandle & SKMaxXEdgeMask)) {
  375. newBounds.size.width += relPoint.x;
  376. if (NSMaxX(newBounds) > NSMaxX(pageBounds))
  377. newBounds.size.width = NSMaxX(pageBounds) - NSMinX(newBounds);
  378. if (NSWidth(newBounds) < minWidth) {
  379. newBounds.size.width = minWidth;
  380. }
  381. } else if ((resizeHandle & SKMinXEdgeMask)) {
  382. newBounds.origin.x += relPoint.x;
  383. newBounds.size.width -= relPoint.x;
  384. if (NSMinX(newBounds) < NSMinX(pageBounds)) {
  385. newBounds.size.width = NSMaxX(newBounds) - NSMinX(pageBounds);
  386. newBounds.origin.x = NSMinX(pageBounds);
  387. }
  388. if (NSWidth(newBounds) < minWidth) {
  389. newBounds.origin.x = NSMaxX(newBounds) - minWidth;
  390. newBounds.size.width = minWidth;
  391. }
  392. }
  393. if ((resizeHandle & SKMaxYEdgeMask)) {
  394. newBounds.size.height += relPoint.y;
  395. if (NSMaxY(newBounds) > NSMaxY(pageBounds)) {
  396. newBounds.size.height = NSMaxY(pageBounds) - NSMinY(newBounds);
  397. }
  398. if (NSHeight(newBounds) < minHeight) {
  399. newBounds.size.height = minHeight;
  400. }
  401. } else if ((resizeHandle & SKMinYEdgeMask)) {
  402. newBounds.origin.y += relPoint.y;
  403. newBounds.size.height -= relPoint.y;
  404. if (NSMinY(newBounds) < NSMinY(pageBounds)) {
  405. newBounds.size.height = NSMaxY(newBounds) - NSMinY(pageBounds);
  406. newBounds.origin.y = NSMinY(pageBounds);
  407. }
  408. if (NSHeight(newBounds) < minHeight) {
  409. newBounds.origin.y = NSMaxY(newBounds) - minHeight;
  410. newBounds.size.height = minHeight;
  411. }
  412. }
  413. return newBounds;
  414. }
  415. */
  416. }