CPDFListView.m 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. //
  2. // CPDFListView.m
  3. // compdfkit-tools
  4. //
  5. // Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
  6. //
  7. // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
  8. // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
  9. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
  10. // This notice may not be removed from this file.
  11. //
  12. #import "CPDFListView.h"
  13. #import "CPDFColorUtils.h"
  14. #import "CPDFSlider.h"
  15. #import "CPDFPageIndicatorView.h"
  16. typedef NS_ENUM(NSInteger, CPDFAnnotationDraggingType) {
  17. CPDFAnnotationDraggingNone = 0,
  18. CPDFAnnotationDraggingCenter,
  19. CPDFAnnotationDraggingTopLeft,
  20. CPDFAnnotationDraggingTopRight,
  21. CPDFAnnotationDraggingBottomLeft,
  22. CPDFAnnotationDraggingBottomRight,
  23. CPDFAnnotationDraggingStart,
  24. CPDFAnnotationDraggingEnd
  25. };
  26. @interface CPDFListView()
  27. @property (nonatomic, strong) CPDFPageIndicatorView * pageIndicatorView;
  28. @property (nonatomic, assign) CPDFAnnotationDraggingType draggingType;
  29. @property (nonatomic, assign) CGPoint draggingPoint;
  30. @property (nonatomic, assign) CGRect topLeftRect;
  31. @property (nonatomic, assign) CGRect bottomLeftRect;
  32. @property (nonatomic, assign) CGRect topRightRect;
  33. @property (nonatomic, assign) CGRect bottomRightRect;
  34. @property (nonatomic, assign) CGRect startPointRect;
  35. @property (nonatomic, assign) CGRect endPointRect;
  36. @property (nonatomic, assign) CGPoint addLinkPoint;
  37. @property (nonatomic, assign) CGRect addLinkRect;
  38. @property (nonatomic, strong) CPDFAnnotation *menuAnnotation;
  39. @property (nonatomic, assign) CGPoint menuPoint;
  40. @property (nonatomic, assign) CPDFPage *menuPage;
  41. @end
  42. @implementation CPDFListView
  43. #pragma mark - Initializers
  44. - (instancetype)initWithFrame:(CGRect)frame {
  45. if (self = [super initWithFrame:frame]) {
  46. self.backgroundColor = [UIColor lightGrayColor];
  47. [self commomInit];
  48. [self addNotification];
  49. }
  50. return self;
  51. }
  52. - (id)initWithCoder:(NSCoder *)decoder {
  53. self = [super initWithCoder:decoder];
  54. if (self) {
  55. self.backgroundColor = [UIColor lightGrayColor];
  56. [self commomInit];
  57. [self addNotification];
  58. }
  59. return self;
  60. }
  61. - (void)setAnnotationMode:(CPDFViewAnnotationMode)annotationMode {
  62. _annotationMode = annotationMode;
  63. if (CPDFViewAnnotationModeHighlight == annotationMode ||
  64. CPDFViewAnnotationModeUnderline == annotationMode ||
  65. CPDFViewAnnotationModeStrikeout == annotationMode ||
  66. CPDFViewAnnotationModeSquiggly == annotationMode) {
  67. self.textSelectionMode = YES;
  68. } else {
  69. self.textSelectionMode = NO;
  70. }
  71. if (CPDFViewAnnotationModeLink == annotationMode) {
  72. self.scrollEnabled = NO;
  73. [self endDrawing];
  74. } else if (CPDFViewAnnotationModeInk == annotationMode) {
  75. self.scrollEnabled = NO;
  76. [self beginDrawing];
  77. } else {
  78. if (self.activeAnnotation) {
  79. self.scrollEnabled = NO;
  80. } else {
  81. self.scrollEnabled = YES;
  82. }
  83. [self endDrawing];
  84. [self becomeFirstResponder];
  85. }
  86. if (CPDFViewAnnotationModeNone != annotationMode) {
  87. CPDFPage *page = self.activeAnnotation.page;
  88. self.activeAnnotation = nil;
  89. [self setNeedsDisplayForPage:page];
  90. }
  91. }
  92. - (void)updateScrollEnabled {
  93. if (self.activeAnnotation) {
  94. self.scrollEnabled = NO;
  95. } else {
  96. if (CPDFViewAnnotationModeLink == self.annotationMode) {
  97. self.scrollEnabled = NO;
  98. } else {
  99. self.scrollEnabled = YES;
  100. }
  101. }
  102. }
  103. - (NSString *)annotationUserName {
  104. NSString *annotationUserName = CPDFKitShareConfig.annotationAuthor;
  105. if (!annotationUserName || [annotationUserName length] <= 0) {
  106. annotationUserName = [[UIDevice currentDevice] name];
  107. }
  108. return annotationUserName ? : @"";
  109. }
  110. - (UIImage *)compressImage:(UIImage *)image size:(CGSize)size {
  111. CGFloat imageScale = 1.0;
  112. if (image.size.width > size.width || image.size.height > size.height) {
  113. imageScale = MIN(size.width / image.size.width, size.height / image.size.height);
  114. }
  115. CGSize newSize = CGSizeMake(image.size.width * imageScale, image.size.height * imageScale);
  116. UIGraphicsBeginImageContext(newSize);
  117. [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
  118. UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
  119. UIGraphicsEndImageContext();
  120. return newImage;
  121. }
  122. #pragma mark - Touch
  123. - (void)touchBeganAtPoint:(CGPoint)point forPage:(CPDFPage *)page {
  124. if (CToolModelAnnotation == self.toolModel) {
  125. } else if (CToolModelForm == self.toolModel) {
  126. } else if (CToolModelEdit == self.toolModel) {
  127. } else {
  128. }
  129. if (self.textSelectionMode) {
  130. } else {
  131. self.addLinkPoint = point;
  132. self.addLinkRect = CGRectZero;
  133. self.draggingType = CPDFAnnotationDraggingNone;
  134. if (!self.activeAnnotation || self.activeAnnotation.page != page) {
  135. return;
  136. }
  137. CGRect topLeftRect = CGRectInset(self.topLeftRect, -5, -5);
  138. CGRect bottomLeftRect = CGRectInset(self.bottomLeftRect, -5, -5);
  139. CGRect topRightRect = CGRectInset(self.topRightRect, -5, -5);
  140. CGRect bottomRightRect = CGRectInset(self.bottomRightRect, -5, -5);
  141. CGRect startPointRect = CGRectInset(self.startPointRect, -5, -5);
  142. CGRect endPointRect = CGRectInset(self.endPointRect, -5, -5);
  143. if (CGRectContainsPoint(topLeftRect, point)) {
  144. self.draggingType = CPDFAnnotationDraggingBottomLeft;
  145. } else if (CGRectContainsPoint(topRightRect, point)) {
  146. self.draggingType = CPDFAnnotationDraggingTopRight;
  147. } else if (CGRectContainsPoint(bottomRightRect, point)) {
  148. self.draggingType = CPDFAnnotationDraggingBottomRight;
  149. } else if (CGRectContainsPoint(startPointRect, point)) {
  150. self.draggingType = CPDFAnnotationDraggingStart;
  151. } else if (CGRectContainsPoint(endPointRect, point)) {
  152. self.draggingType = CPDFAnnotationDraggingEnd;
  153. } else if ([page annotation:self.activeAnnotation atPoint:point]) {
  154. self.draggingType = CPDFAnnotationDraggingCenter;
  155. }
  156. self.draggingPoint = point;
  157. if (CPDFAnnotationDraggingCenter == self.draggingType) {
  158. if ([self.activeAnnotation isKindOfClass:[CPDFFreeTextAnnotation class]] ||
  159. [self.activeAnnotation isKindOfClass:[CPDFSignatureAnnotation class]]) {
  160. // [self addMagnifierAtPoint:point forPage:page];
  161. }
  162. }
  163. }
  164. }
  165. - (void)touchMovedAtPoint:(CGPoint)point forPage:(CPDFPage *)page {
  166. if (CToolModelAnnotation == self.toolModel) {
  167. } else if (CToolModelForm == self.toolModel) {
  168. } else if (CToolModelEdit == self.toolModel) {
  169. } else {
  170. }
  171. if (self.textSelectionMode) {
  172. } else if (CPDFAnnotationDraggingNone != self.draggingType) {
  173. [self moveAnnotation:self.activeAnnotation fromPoint:self.draggingPoint toPoint:point forType:self.draggingType];
  174. [self setNeedsDisplayForPage:page];
  175. self.draggingPoint = point;
  176. if (CPDFAnnotationDraggingCenter == self.draggingType) {
  177. if ([self.activeAnnotation isKindOfClass:[CPDFFreeTextAnnotation class]] ||
  178. [self.activeAnnotation isKindOfClass:[CPDFSignatureAnnotation class]]) {
  179. // [self addMagnifierAtPoint:point forPage:page];
  180. }
  181. }
  182. } else if (CPDFViewAnnotationModeLink == self.annotationMode) {
  183. CGRect rect = CGRectZero;
  184. if (point.x > self.addLinkPoint.x) {
  185. rect.origin.x = self.addLinkPoint.x;
  186. rect.size.width = point.x-self.addLinkPoint.x;
  187. } else {
  188. rect.origin.x = point.x;
  189. rect.size.width = self.addLinkPoint.x-point.x;
  190. }
  191. if (point.y > self.addLinkPoint.y) {
  192. rect.origin.y = self.addLinkPoint.y;
  193. rect.size.height = point.y-self.addLinkPoint.y;
  194. } else {
  195. rect.origin.y = point.y;
  196. rect.size.height = self.addLinkPoint.y-point.y;
  197. }
  198. self.addLinkRect = rect;
  199. [self setNeedsDisplayForPage:page];
  200. }
  201. }
  202. - (void)touchEndedAtPoint:(CGPoint)point forPage:(CPDFPage *)page {
  203. if (CToolModelAnnotation == self.toolModel) {
  204. } else if (CToolModelForm == self.toolModel) {
  205. } else if (CToolModelEdit == self.toolModel) {
  206. } else {
  207. }
  208. if (self.textSelectionMode) {
  209. if (self.currentSelection) {
  210. [self addAnnotation:self.annotationMode atPoint:point forPage:page];
  211. } else {
  212. CPDFAnnotation *annotation = [page annotationAtPoint:point];
  213. if ([annotation isKindOfClass:[CPDFMarkupAnnotation class]]) {
  214. // [self showMenuForAnnotation:annotation];
  215. }
  216. }
  217. } else if (CPDFAnnotationDraggingNone == self.draggingType) {
  218. if (self.activeAnnotation) {
  219. CPDFPage *previousPage = self.activeAnnotation.page;
  220. self.activeAnnotation = nil;
  221. [self setNeedsDisplayForPage:previousPage];
  222. [self updateScrollEnabled];
  223. } else {
  224. if (CPDFViewAnnotationModeNone == self.annotationMode) {
  225. CPDFAnnotation *annotation = [page annotationAtPoint:point];
  226. if ([annotation isKindOfClass:[CPDFTextAnnotation class]]) {
  227. if ([self.performDelegate respondsToSelector:@selector(PDFViewPerformOpenNote:forAnnotation:)]) {
  228. [self.performDelegate PDFViewPerformOpenNote:self forAnnotation:annotation];
  229. }
  230. } else if ([annotation isKindOfClass:[CPDFMarkupAnnotation class]]) {
  231. // if (CGRectContainsPoint(annotation.bounds, point)) {
  232. // [self showMenuForAnnotation:annotation];
  233. // } else {
  234. // if ([self.performDelegate respondsToSelector:@selector(PDFViewPerformPopup:forAnnotation:)]) {
  235. // [self.performDelegate PDFViewPerformPopup:self forAnnotation:(CPDFMarkupAnnotation *)annotation];
  236. // }
  237. // }
  238. } else if ([annotation isKindOfClass:[CPDFLinkAnnotation class]]) {
  239. [super touchEndedAtPoint:point forPage:page];
  240. } else if ([annotation isKindOfClass:[CPDFMovieAnnotation class]]) {
  241. [super touchEndedAtPoint:point forPage:page];
  242. } else if ([annotation isKindOfClass:[CPDFWidgetAnnotation class]]) {
  243. if ([annotation isKindOfClass:[CPDFSignatureWidgetAnnotation class]]) {
  244. // if ([(CPDFSignatureWidgetAnnotation *)annotation isSigned]) {
  245. // [self showMenuForAnnotation:annotation];
  246. // } else {
  247. // if ([self.performDelegate respondsToSelector:@selector(PDFViewPerformSignatureWidget:forAnnotation:)]) {
  248. // [self.performDelegate PDFViewPerformSignatureWidget:self forAnnotation:(CPDFSignatureWidgetAnnotation *)annotation];
  249. // }
  250. // }
  251. } else {
  252. [super touchEndedAtPoint:point forPage:page];
  253. }
  254. } else {
  255. self.activeAnnotation = annotation;
  256. [self setNeedsDisplayForPage:page];
  257. [self updateScrollEnabled];
  258. // [self showMenuForAnnotation:annotation];
  259. //
  260. if (!self.activeAnnotation) {
  261. if ([self.performDelegate respondsToSelector:@selector(PDFViewPerformTouchEnded:)]) {
  262. [self.performDelegate PDFViewPerformTouchEnded:self];
  263. }
  264. }
  265. }
  266. } else if (CPDFViewAnnotationModeLink == self.annotationMode) {
  267. // if (CGRectIsEmpty(self.addLinkRect)) {
  268. // CPDFAnnotation *annotation = [page annotationAtPoint:point];
  269. // if ([annotation isKindOfClass:[CPDFLinkAnnotation class]]) {
  270. // self.activeAnnotation = annotation;
  271. // [self setNeedsDisplayForPage:page];
  272. // [self updateScrollEnabled];
  273. //
  274. // [self showMenuForAnnotation:annotation];
  275. // }
  276. // } else {
  277. // [self addAnnotationLinkAtPoint:point forPage:page];
  278. // }
  279. } else if (CPDFViewAnnotationModeFreeText == self.annotationMode) {
  280. // [self addAnnotationFreeTextAtPoint:point forPage:page];
  281. } else if (CPDFViewAnnotationModeStamp == self.annotationMode) {
  282. // [self addAnnotationAtPoint:point forPage:page];
  283. if ([self.performDelegate respondsToSelector:@selector(PDFViewPerformTouchEnded:)]) {
  284. [self.performDelegate PDFViewPerformTouchEnded:self];
  285. }
  286. } else if (CPDFViewAnnotationModeImage == self.annotationMode) {
  287. // [self addAnnotationAtPoint:point forPage:page];
  288. if ([self.performDelegate respondsToSelector:@selector(PDFViewPerformTouchEnded:)]) {
  289. [self.performDelegate PDFViewPerformTouchEnded:self];
  290. }
  291. } else {
  292. [self addAnnotation:self.annotationMode atPoint:point forPage:page];
  293. }
  294. }
  295. } else {
  296. if (CPDFAnnotationDraggingCenter != self.draggingType) {
  297. if ([self.activeAnnotation isKindOfClass:[CPDFFreeTextAnnotation class]] ||
  298. [self.activeAnnotation isKindOfClass:[CPDFStampAnnotation class]] ||
  299. [self.activeAnnotation isKindOfClass:[CPDFSignatureAnnotation class]]) {
  300. [self.activeAnnotation updateAppearanceStream];
  301. [self setNeedsDisplayForPage:page];
  302. }
  303. }
  304. self.draggingType = CPDFAnnotationDraggingNone;
  305. // [self showMenuForAnnotation:self.activeAnnotation];
  306. }
  307. // [self removeMagnifier];
  308. }
  309. - (void)touchCancelledAtPoint:(CGPoint)point forPage:(CPDFPage *)page {
  310. if (CToolModelAnnotation == self.toolModel) {
  311. } else if (CToolModelForm == self.toolModel) {
  312. } else if (CToolModelEdit == self.toolModel) {
  313. } else {
  314. }
  315. self.draggingType = CPDFAnnotationDraggingNone;
  316. }
  317. - (NSArray<UIMenuItem *> *)menuItemsAtPoint:(CGPoint)point forPage:(CPDFPage *)page {
  318. if([self.performDelegate respondsToSelector:@selector(PDFListView:customizeMenuForPage:forPagePoint:)])
  319. return [self.performDelegate PDFListView:self customizeMenuForPage:page forPagePoint:point];
  320. return [super menuItemsAtPoint:point forPage:page];
  321. }
  322. #pragma mark - Private method
  323. - (void)commomInit {
  324. _pageSliderView = [[CPDFSlider alloc] initWithPDFView:self];
  325. _pageSliderView.frame = CGRectMake(self.bounds.size.width-22, 0, 22, self.bounds.size.height);
  326. _pageSliderView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin;
  327. [self addSubview:self.pageSliderView];
  328. _pageIndicatorView = [[CPDFPageIndicatorView alloc] init];
  329. __weak typeof(self) weakSelf = self;
  330. _pageIndicatorView.touchCallBack = ^{
  331. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:NSLocalizedString(@"Go to page", nil) preferredStyle:UIAlertControllerStyleAlert];
  332. [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  333. }]];
  334. [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Done", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  335. UITextField *pageTextField = alertController.textFields.firstObject;
  336. NSInteger pageIndex = [pageTextField.text integerValue] - 1;
  337. if (pageIndex > weakSelf.document.pageCount){
  338. pageIndex = weakSelf.document.pageCount;
  339. } else if(pageIndex<0){
  340. pageIndex = 0;
  341. } else if(pageTextField.text.length == 0){
  342. pageIndex = (int)weakSelf.currentPageIndex;
  343. }
  344. [weakSelf goToPageIndex:pageIndex animated:YES];
  345. }]];
  346. [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
  347. textField.placeholder = NSLocalizedString(@"Enter a page number", nil);
  348. textField.keyboardType = UIKeyboardTypeNumberPad;
  349. }];
  350. UIViewController *tRootViewControl = [UIApplication sharedApplication].keyWindow.rootViewController;
  351. if ([tRootViewControl presentedViewController]) {
  352. tRootViewControl = [tRootViewControl presentedViewController];
  353. }
  354. [tRootViewControl presentViewController:alertController animated:true completion:nil];
  355. };
  356. }
  357. - (void)addNotification {
  358. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(documentChangedNotification:) name:CPDFViewDocumentChangedNotification object:nil];
  359. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pageChangedNotification:) name:CPDFViewPageChangedNotification object:nil];
  360. }
  361. - (void)showPageNumIndicator {
  362. __weak typeof(self) weakSelf = self;
  363. if(![self.pageIndicatorView superview])
  364. [self.pageIndicatorView showInView:weakSelf position:CPDFPageIndicatorViewPositionLeftBottom];
  365. [self.pageIndicatorView updatePageCount:weakSelf.document.pageCount currentPageIndex:self.currentPageIndex + 1];
  366. }
  367. #pragma mark - NotificationCenter
  368. - (void)documentChangedNotification:(NSNotification *)notification {
  369. CPDFView *pdfview = notification.object;
  370. if (pdfview.document == self.document) {
  371. [self showPageNumIndicator];
  372. [self.pageSliderView reloadData];
  373. }
  374. }
  375. - (void)pageChangedNotification:(NSNotification *)notification {
  376. CPDFView *pdfview = notification.object;
  377. if (pdfview.document == self.document) {
  378. [self showPageNumIndicator];
  379. [self.pageSliderView reloadData];
  380. }
  381. }
  382. #pragma mark - Rendering
  383. - (void)drawPage:(CPDFPage *)page toContext:(CGContextRef)context {
  384. if (CPDFViewAnnotationModeLink == self.annotationMode) {
  385. CGContextSetLineWidth(context, 1.0);
  386. CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:255.0/255.f green:255.0/255.f blue:255.0/255.f alpha:0.8].CGColor);
  387. CGContextSetFillColorWithColor(context, [UIColor colorWithRed:100.0/255.f green:149.0/255.f blue:237.0/255.f alpha:0.4].CGColor);
  388. CGContextAddRect(context, self.addLinkRect);
  389. CGContextDrawPath(context, kCGPathFillStroke);
  390. }
  391. if (self.activeAnnotation.page != page) {
  392. return;
  393. }
  394. CGSize dragDotSize = CGSizeMake(30, 30);
  395. CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:72.0/255.0 green:183.0/255.0 blue:247.0/255.0 alpha:1.0].CGColor);
  396. if ([self.activeAnnotation isKindOfClass:[CPDFLineAnnotation class]]) {
  397. CPDFLineAnnotation *line = (CPDFLineAnnotation *)self.activeAnnotation;
  398. CGPoint startPoint = line.startPoint;
  399. CGPoint endPoint = line.endPoint;
  400. CGPoint tStartPoint = startPoint;
  401. CGPoint tEndPoint = endPoint;
  402. float final = 40;
  403. if (fabs(tStartPoint.x - tEndPoint.x) < 0.00001) {
  404. if (tStartPoint.y > tEndPoint.y) {
  405. tStartPoint.y += final;
  406. tEndPoint.y -= final;
  407. } else {
  408. tStartPoint.y -= final;
  409. tEndPoint.y += final;
  410. }
  411. } else if (fabs(tStartPoint.y - tEndPoint.y) < 0.00001) {
  412. if (tStartPoint.x > tEndPoint.x) {
  413. tStartPoint.x += final;
  414. tEndPoint.x -= final;
  415. } else {
  416. tStartPoint.x -= final;
  417. tEndPoint.x += final;
  418. }
  419. } else {
  420. double k = (tEndPoint.y - tStartPoint.y)/(tEndPoint.x - tStartPoint.x);
  421. double atank = atan(k);
  422. if (endPoint.x > startPoint.x) {
  423. tEndPoint.x += cos(atank) * final;
  424. tEndPoint.y += sin(atank) * final;
  425. tStartPoint.x -= cos(atank) * final;
  426. tStartPoint.y -= sin(atank) * final;
  427. } else {
  428. tEndPoint.x -= cos(atank) * final;
  429. tEndPoint.y -= sin(atank) * final;
  430. tStartPoint.x += cos(atank) * final;
  431. tStartPoint.y += sin(atank) * final;
  432. }
  433. }
  434. CGContextSetLineWidth(context, 1.0);
  435. CGFloat dashArray[] = {3,3};
  436. CGContextSetLineDash(context, 0, dashArray, 2);
  437. CGContextMoveToPoint(context, tStartPoint.x, tStartPoint.y);
  438. CGContextAddLineToPoint(context, startPoint.x, startPoint.y);
  439. CGContextStrokePath(context);
  440. CGContextMoveToPoint(context, tEndPoint.x, tEndPoint.y);
  441. CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
  442. CGContextStrokePath(context);
  443. CGRect startPointRect = CGRectMake(tStartPoint.x - dragDotSize.width/2.0,
  444. tStartPoint.y - dragDotSize.height/2.0,
  445. dragDotSize.width, dragDotSize.height);
  446. CGRect endPointRect = CGRectMake(tEndPoint.x - dragDotSize.width/2.0,
  447. tEndPoint.y - dragDotSize.height/2.0,
  448. dragDotSize.width, dragDotSize.height);
  449. UIImage *image = [UIImage imageNamed:@"annotation_drag_dot.png" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil];
  450. CGImageRef dragDotImage = image.CGImage;
  451. CGContextDrawImage(context, startPointRect, dragDotImage);
  452. CGContextDrawImage(context, endPointRect, dragDotImage);
  453. self.startPointRect = startPointRect;
  454. self.endPointRect = endPointRect;
  455. } else if ([self.activeAnnotation isKindOfClass:[CPDFFreeTextAnnotation class]]) {
  456. CGRect rect = CGRectInset(self.activeAnnotation.bounds, -dragDotSize.width/2.0, -dragDotSize.height/2.0);
  457. CGContextSetLineWidth(context, 1.0);
  458. CGFloat lengths[] = {6, 6};
  459. CGContextSetLineDash(context, 0, lengths, 2);
  460. CGContextStrokeRect(context, rect);
  461. CGContextStrokePath(context);
  462. CGAffineTransform transform = [page transform];
  463. if (CPDFKitShareConfig.enableAnnotationNoRotate) {
  464. rect = CGRectApplyAffineTransform(rect, transform);
  465. }
  466. CGRect leftCenterRect = CGRectMake(CGRectGetMinX(rect)-dragDotSize.width/2.0,
  467. CGRectGetMidY(rect)-dragDotSize.height/2.0,
  468. dragDotSize.width, dragDotSize.height);
  469. CGRect rightCenterRect = CGRectMake(CGRectGetMaxX(rect)-dragDotSize.width/2.0,
  470. CGRectGetMidY(rect)-dragDotSize.height/2.0,
  471. dragDotSize.width, dragDotSize.height);
  472. if (CPDFKitShareConfig.enableAnnotationNoRotate) {
  473. leftCenterRect = CGRectApplyAffineTransform(leftCenterRect, CGAffineTransformInvert(transform));
  474. rightCenterRect = CGRectApplyAffineTransform(rightCenterRect, CGAffineTransformInvert(transform));
  475. }
  476. UIImage *image = [UIImage imageNamed:@"annotation_drag_dot.png" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil];
  477. CGImageRef dragDotImage = image.CGImage;
  478. CGContextDrawImage(context, leftCenterRect, dragDotImage);
  479. CGContextDrawImage(context, rightCenterRect, dragDotImage);
  480. self.startPointRect = leftCenterRect;
  481. self.endPointRect = rightCenterRect;
  482. } else {
  483. CGRect rect = CGRectInset(self.activeAnnotation.bounds, -dragDotSize.width/2.0, -dragDotSize.height/2.0);
  484. CGContextSetLineWidth(context, 1.0);
  485. CGFloat lengths[] = {6, 6};
  486. CGContextSetLineDash(context, 0, lengths, 2);
  487. CGContextStrokeRect(context, rect);
  488. CGContextStrokePath(context);
  489. if ([self.activeAnnotation isKindOfClass:[CPDFSoundAnnotation class]] ||
  490. [self.activeAnnotation isKindOfClass:[CPDFMovieAnnotation class]]) {
  491. return;
  492. }
  493. CGRect topLeftRect = CGRectMake(CGRectGetMinX(rect)-dragDotSize.width/2.0,
  494. CGRectGetMaxY(rect)-dragDotSize.height/2.0,
  495. dragDotSize.width, dragDotSize.height);
  496. CGRect bottomLeftRect = CGRectMake(CGRectGetMinX(rect)-dragDotSize.width/2.0,
  497. CGRectGetMinY(rect)-dragDotSize.height/2.0,
  498. dragDotSize.width, dragDotSize.height);
  499. CGRect topRightRect = CGRectMake(CGRectGetMaxX(rect)-dragDotSize.width/2.0,
  500. CGRectGetMaxY(rect)-dragDotSize.height/2.0,
  501. dragDotSize.width, dragDotSize.height);
  502. CGRect bottomRightRect = CGRectMake(CGRectGetMaxX(rect)-dragDotSize.width/2.0,
  503. CGRectGetMinY(rect)-dragDotSize.height/2.0,
  504. dragDotSize.width, dragDotSize.height);
  505. UIImage *image = [UIImage imageNamed:@"annotation_drag_dot.png" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil];
  506. CGImageRef dragDotImage = image.CGImage;
  507. CGContextDrawImage(context, topLeftRect, dragDotImage);
  508. CGContextDrawImage(context, bottomLeftRect, dragDotImage);
  509. CGContextDrawImage(context, topRightRect, dragDotImage);
  510. CGContextDrawImage(context, bottomRightRect, dragDotImage);
  511. self.topLeftRect = topLeftRect;
  512. self.bottomLeftRect = bottomLeftRect;
  513. self.topRightRect = topRightRect;
  514. self.bottomRightRect = bottomRightRect;
  515. }
  516. }
  517. #pragma mark - Annotation
  518. - (void)moveAnnotation:(CPDFAnnotation *)annotation fromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint forType:(CPDFAnnotationDraggingType)draggingType {
  519. CGRect bounds = annotation.bounds;
  520. CGPoint offsetPoint = CGPointMake(toPoint.x - fromPoint.x, toPoint.y - fromPoint.y);
  521. CGFloat scale = bounds.size.height/bounds.size.width;
  522. if ([annotation isKindOfClass:[CPDFLineAnnotation class]]) {
  523. CPDFLineAnnotation *line = (CPDFLineAnnotation *)annotation;
  524. CGPoint startPoint = line.startPoint;
  525. CGPoint endPoint = line.endPoint;
  526. switch (draggingType) {
  527. case CPDFAnnotationDraggingCenter:
  528. {
  529. startPoint.x += offsetPoint.x;
  530. startPoint.y += offsetPoint.y;
  531. endPoint.x += offsetPoint.x;
  532. endPoint.y += offsetPoint.y;
  533. }
  534. break;
  535. case CPDFAnnotationDraggingStart:
  536. {
  537. startPoint.x += offsetPoint.x;
  538. startPoint.y += offsetPoint.y;
  539. }
  540. break;
  541. case CPDFAnnotationDraggingEnd:
  542. {
  543. endPoint.x += offsetPoint.x;
  544. endPoint.y += offsetPoint.y;
  545. }
  546. break;
  547. default:
  548. break;
  549. }
  550. line.startPoint = startPoint;
  551. line.endPoint = endPoint;
  552. bounds = line.bounds;
  553. } else if ([annotation isKindOfClass:[CPDFFreeTextAnnotation class]]) {
  554. CGAffineTransform transform = [annotation.page transform];
  555. if (CPDFKitShareConfig.enableAnnotationNoRotate) {
  556. bounds = CGRectApplyAffineTransform(bounds, transform);
  557. toPoint = CGPointApplyAffineTransform(toPoint, transform);
  558. fromPoint = CGPointApplyAffineTransform(fromPoint, transform);
  559. offsetPoint = CGPointMake(toPoint.x - fromPoint.x, toPoint.y - fromPoint.y);
  560. }
  561. CPDFFreeTextAnnotation *freeText = (CPDFFreeTextAnnotation *)annotation;
  562. NSDictionary *attributes = @{NSFontAttributeName : freeText.font};
  563. switch (draggingType) {
  564. case CPDFAnnotationDraggingCenter:
  565. {
  566. bounds.origin.x += offsetPoint.x;
  567. bounds.origin.y += offsetPoint.y;
  568. }
  569. break;
  570. case CPDFAnnotationDraggingStart:
  571. {
  572. CGFloat x = CGRectGetMaxX(bounds);
  573. bounds.size.width -= offsetPoint.x;
  574. bounds.size.width = MAX(bounds.size.width, 5.0);
  575. bounds.origin.x = x - bounds.size.width;
  576. CGRect rect = [freeText.contents boundingRectWithSize:CGSizeMake(bounds.size.width, CGFLOAT_MAX)
  577. options:NSStringDrawingUsesLineFragmentOrigin
  578. attributes:attributes
  579. context:nil];
  580. bounds.origin.y = CGRectGetMaxY(bounds) - rect.size.height;
  581. bounds.size.height = rect.size.height;
  582. }
  583. break;
  584. case CPDFAnnotationDraggingEnd:
  585. {
  586. bounds.size.width += offsetPoint.x;
  587. bounds.size.width = MAX(bounds.size.width, 5.0);
  588. CGRect rect = [freeText.contents boundingRectWithSize:CGSizeMake(bounds.size.width, CGFLOAT_MAX)
  589. options:NSStringDrawingUsesLineFragmentOrigin
  590. attributes:attributes
  591. context:nil];
  592. bounds.origin.y = CGRectGetMaxY(bounds) - rect.size.height;
  593. bounds.size.height = rect.size.height;
  594. }
  595. break;
  596. default:
  597. break;
  598. }
  599. if (CPDFKitShareConfig.enableAnnotationNoRotate) {
  600. bounds = CGRectApplyAffineTransform(bounds, CGAffineTransformInvert(transform));
  601. }
  602. } else {
  603. switch (draggingType) {
  604. case CPDFAnnotationDraggingCenter:
  605. {
  606. bounds.origin.x += offsetPoint.x;
  607. bounds.origin.y += offsetPoint.y;
  608. }
  609. break;
  610. case CPDFAnnotationDraggingTopLeft:
  611. {
  612. CGFloat x = CGRectGetMaxX(bounds);
  613. bounds.size.width -= offsetPoint.x;
  614. bounds.size.height += offsetPoint.y;
  615. if ([annotation isKindOfClass:[CPDFStampAnnotation class]] ||
  616. [annotation isKindOfClass:[CPDFSignatureAnnotation class]] ||
  617. [annotation isKindOfClass:[CPDFInkAnnotation class]]) {
  618. bounds.size.height = bounds.size.width*scale;
  619. bounds.size.width = MAX(bounds.size.width, 5.0);
  620. bounds.size.height = MAX(bounds.size.height, 5.0*scale);
  621. } else {
  622. bounds.size.width = MAX(bounds.size.width, 5.0);
  623. bounds.size.height = MAX(bounds.size.height, 5.0);
  624. }
  625. bounds.origin.x = x - bounds.size.width;
  626. }
  627. break;
  628. case CPDFAnnotationDraggingBottomLeft:
  629. {
  630. CGFloat x = CGRectGetMaxX(bounds);
  631. CGFloat y = CGRectGetMaxY(bounds);
  632. bounds.size.width -= offsetPoint.x;
  633. bounds.size.height -= offsetPoint.y;
  634. if ([annotation isKindOfClass:[CPDFStampAnnotation class]] ||
  635. [annotation isKindOfClass:[CPDFSignatureAnnotation class]] ||
  636. [annotation isKindOfClass:[CPDFInkAnnotation class]]) {
  637. bounds.size.height = bounds.size.width*scale;
  638. bounds.size.width = MAX(bounds.size.width, 5.0);
  639. bounds.size.height = MAX(bounds.size.height, 5.0*scale);
  640. } else {
  641. bounds.size.width = MAX(bounds.size.width, 5.0);
  642. bounds.size.height = MAX(bounds.size.height, 5.0);
  643. }
  644. bounds.origin.x = x - bounds.size.width;
  645. bounds.origin.y = y - bounds.size.height;
  646. }
  647. break;
  648. case CPDFAnnotationDraggingTopRight:
  649. {
  650. bounds.size.width += offsetPoint.x;
  651. bounds.size.height += offsetPoint.y;
  652. if ([annotation isKindOfClass:[CPDFStampAnnotation class]] ||
  653. [annotation isKindOfClass:[CPDFSignatureAnnotation class]] ||
  654. [annotation isKindOfClass:[CPDFInkAnnotation class]]) {
  655. bounds.size.height = bounds.size.width*scale;
  656. bounds.size.width = MAX(bounds.size.width, 5.0);
  657. bounds.size.height = MAX(bounds.size.height, 5.0*scale);
  658. } else {
  659. bounds.size.width = MAX(bounds.size.width, 5.0);
  660. bounds.size.height = MAX(bounds.size.height, 5.0);
  661. }
  662. }
  663. break;
  664. case CPDFAnnotationDraggingBottomRight:
  665. {
  666. CGFloat y = CGRectGetMaxY(bounds);
  667. bounds.size.width += offsetPoint.x;
  668. bounds.size.height -= offsetPoint.y;
  669. if ([annotation isKindOfClass:[CPDFStampAnnotation class]] ||
  670. [annotation isKindOfClass:[CPDFSignatureAnnotation class]] ||
  671. [annotation isKindOfClass:[CPDFInkAnnotation class]]) {
  672. bounds.size.height = bounds.size.width*scale;
  673. bounds.size.width = MAX(bounds.size.width, 5.0);
  674. bounds.size.height = MAX(bounds.size.height, 5.0*scale);
  675. } else {
  676. bounds.size.width = MAX(bounds.size.width, 5.0);
  677. bounds.size.height = MAX(bounds.size.height, 5.0);
  678. }
  679. bounds.origin.y = y - bounds.size.height;
  680. }
  681. break;
  682. default:
  683. break;
  684. }
  685. if (CGRectGetMinX(bounds) < 0) {
  686. bounds.origin.x = 0;
  687. }
  688. if (CGRectGetMaxX(bounds) > CGRectGetWidth(annotation.page.bounds)) {
  689. bounds.origin.x = CGRectGetWidth(annotation.page.bounds) - CGRectGetWidth(bounds);
  690. }
  691. if (CGRectGetMinY(bounds) < 0) {
  692. bounds.origin.y = 0;
  693. }
  694. if (CGRectGetMaxY(bounds) > CGRectGetHeight(annotation.page.bounds)) {
  695. bounds.origin.y = CGRectGetHeight(annotation.page.bounds) - CGRectGetHeight(bounds);
  696. }
  697. }
  698. annotation.bounds = bounds;
  699. }
  700. - (void)addAnnotation:(CPDFViewAnnotationMode)mode atPoint:(CGPoint)point forPage:(CPDFPage *)page {
  701. CPDFAnnotation *annotation = nil;
  702. switch (mode) {
  703. case CPDFViewAnnotationModeNote:
  704. {
  705. CGFloat width = 57.0/1.5;
  706. annotation = [[CPDFTextAnnotation alloc] initWithDocument:self.document];
  707. annotation.bounds = CGRectMake(point.x-width/2.0, point.y-width/2.0, width, width);
  708. }
  709. break;
  710. case CPDFViewAnnotationModeHighlight:
  711. {
  712. if (!self.currentSelection) {
  713. return;
  714. }
  715. NSMutableArray *quadrilateralPoints = [NSMutableArray array];
  716. annotation = [[CPDFMarkupAnnotation alloc] initWithDocument:self.document markupType:CPDFMarkupTypeHighlight];
  717. for (CPDFSelection *selection in self.currentSelection.selectionsByLine) {
  718. CGRect bounds = selection.bounds;
  719. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds))]];
  720. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))]];
  721. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds))]];
  722. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds))]];
  723. }
  724. [(CPDFMarkupAnnotation *)annotation setQuadrilateralPoints:quadrilateralPoints];
  725. [(CPDFMarkupAnnotation *)annotation setMarkupText:self.currentSelection.string];
  726. [self clearSelection];
  727. }
  728. break;
  729. case CPDFViewAnnotationModeUnderline:
  730. {
  731. if (!self.currentSelection) {
  732. return;
  733. }
  734. NSMutableArray *quadrilateralPoints = [NSMutableArray array];
  735. annotation = [[CPDFMarkupAnnotation alloc] initWithDocument:self.document markupType:CPDFMarkupTypeUnderline];
  736. for (CPDFSelection *selection in self.currentSelection.selectionsByLine) {
  737. CGRect bounds = selection.bounds;
  738. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds))]];
  739. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))]];
  740. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds))]];
  741. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds))]];
  742. }
  743. [(CPDFMarkupAnnotation *)annotation setQuadrilateralPoints:quadrilateralPoints];
  744. [(CPDFMarkupAnnotation *)annotation setMarkupText:self.currentSelection.string];
  745. [self clearSelection];
  746. }
  747. break;
  748. case CPDFViewAnnotationModeStrikeout:
  749. {
  750. if (!self.currentSelection) {
  751. return;
  752. }
  753. NSMutableArray *quadrilateralPoints = [NSMutableArray array];
  754. annotation = [[CPDFMarkupAnnotation alloc] initWithDocument:self.document markupType:CPDFMarkupTypeStrikeOut];
  755. for (CPDFSelection *selection in self.currentSelection.selectionsByLine) {
  756. CGRect bounds = selection.bounds;
  757. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds))]];
  758. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))]];
  759. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds))]];
  760. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds))]];
  761. }
  762. [(CPDFMarkupAnnotation *)annotation setQuadrilateralPoints:quadrilateralPoints];
  763. [(CPDFMarkupAnnotation *)annotation setMarkupText:self.currentSelection.string];
  764. [self clearSelection];
  765. }
  766. break;
  767. case CPDFViewAnnotationModeSquiggly:
  768. {
  769. if (!self.currentSelection) {
  770. return;
  771. }
  772. NSMutableArray *quadrilateralPoints = [NSMutableArray array];
  773. annotation = [[CPDFMarkupAnnotation alloc] initWithDocument:self.document markupType:CPDFMarkupTypeSquiggly];
  774. for (CPDFSelection *selection in self.currentSelection.selectionsByLine) {
  775. CGRect bounds = selection.bounds;
  776. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds))]];
  777. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))]];
  778. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds))]];
  779. [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds))]];
  780. }
  781. [(CPDFMarkupAnnotation *)annotation setQuadrilateralPoints:quadrilateralPoints];
  782. [(CPDFMarkupAnnotation *)annotation setMarkupText:self.currentSelection.string];
  783. [self clearSelection];
  784. }
  785. break;
  786. case CPDFViewAnnotationModeCircle:
  787. {
  788. annotation = [[CPDFCircleAnnotation alloc] initWithDocument:self.document];
  789. annotation.bounds = CGRectMake(point.x-50, point.y-50, 100, 100);
  790. }
  791. break;
  792. case CPDFViewAnnotationModeSquare:
  793. {
  794. annotation = [[CPDFSquareAnnotation alloc] initWithDocument:self.document];
  795. annotation.bounds = CGRectMake(point.x-50, point.y-50, 100, 100);
  796. }
  797. break;
  798. case CPDFViewAnnotationModeArrow:
  799. {
  800. annotation = [[CPDFLineAnnotation alloc] initWithDocument:self.document];
  801. [(CPDFLineAnnotation *)annotation setStartPoint:CGPointMake(point.x-50, point.y)];
  802. [(CPDFLineAnnotation *)annotation setEndPoint:CGPointMake(point.x+50, point.y)];
  803. [(CPDFLineAnnotation *)annotation setEndLineStyle:CPDFLineStyleClosedArrow];
  804. }
  805. break;
  806. case CPDFViewAnnotationModeLine:
  807. {
  808. annotation = [[CPDFLineAnnotation alloc] initWithDocument:self.document];
  809. [(CPDFLineAnnotation *)annotation setStartPoint:CGPointMake(point.x-50, point.y)];
  810. [(CPDFLineAnnotation *)annotation setEndPoint:CGPointMake(point.x+50, point.y)];
  811. }
  812. break;
  813. default:
  814. break;
  815. }
  816. if (!annotation) {
  817. return;
  818. }
  819. [annotation setModificationDate:[NSDate date]];
  820. [annotation setUserName:[self annotationUserName]];
  821. [page addAnnotation:annotation];
  822. if ([annotation isKindOfClass:[CPDFTextAnnotation class]]) {
  823. [self setNeedsDisplayForPage:page];
  824. // if ([self.performDelegate respondsToSelector:@selector(PDFViewPerformOpenNote:forAnnotation:)]) {
  825. // [self.performDelegate PDFViewPerformOpenNote:self forAnnotation:annotation];
  826. // }
  827. } else if ([annotation isKindOfClass:[CPDFMarkupAnnotation class]]) {
  828. [self setNeedsDisplayForPage:page];
  829. } else {
  830. self.activeAnnotation = annotation;
  831. [self setNeedsDisplayForPage:page];
  832. [self updateScrollEnabled];
  833. // [self showMenuForAnnotation:annotation];
  834. }
  835. }
  836. - (void)addAnnotation:(CPDFAnnotation *)annotation forPage:(CPDFPage *)page {
  837. if (!annotation || !page) {
  838. return;
  839. }
  840. [annotation setModificationDate:[NSDate date]];
  841. [annotation setUserName:[self annotationUserName]];
  842. [page addAnnotation:annotation];
  843. self.activeAnnotation = annotation;
  844. [self setNeedsDisplayForPage:page];
  845. [self updateScrollEnabled];
  846. // [self showMenuForAnnotation:annotation];
  847. }
  848. - (void)addAnnotation:(CPDFAnnotation *)annotation {
  849. CPDFPage *page = [self.document pageAtIndex:self.currentPageIndex];
  850. CGPoint center = [self convertPoint:self.center toPage:page];
  851. if (CGPointEqualToPoint(center, CGPointZero)) {
  852. return;
  853. }
  854. CGRect bounds = annotation.bounds;
  855. bounds.origin.x = center.x-bounds.size.width/2.0;
  856. bounds.origin.y = center.y-bounds.size.height/2.0;
  857. bounds.origin.y = MIN(MAX(0, bounds.origin.y), page.bounds.size.height-bounds.size.height);
  858. annotation.bounds = bounds;
  859. [self addAnnotation:annotation forPage:page];
  860. }
  861. @end