@amafil/react-native-pdf-toolkit 1.1.2 → 1.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -57
- package/android/.gradle/8.5/executionHistory/executionHistory.bin +0 -0
- package/android/.gradle/8.5/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.5/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/8.5/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/file-system.probe +0 -0
- package/android/build/.transforms/2892d280277a194daf04e3af971b529e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/RNPDFPdfViewManagerDelegate.dex +0 -0
- package/android/build/.transforms/2892d280277a194daf04e3af971b529e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/RNPDFPdfViewManagerInterface.dex +0 -0
- package/android/build/.transforms/2892d280277a194daf04e3af971b529e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/org/wonday/pdf/PdfManager.dex +0 -0
- package/android/build/.transforms/2892d280277a194daf04e3af971b529e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/org/wonday/pdf/PdfView$1.dex +0 -0
- package/android/build/.transforms/2892d280277a194daf04e3af971b529e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/org/wonday/pdf/PdfView$2.dex +0 -0
- package/android/build/.transforms/2892d280277a194daf04e3af971b529e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/org/wonday/pdf/PdfView$3.dex +0 -0
- package/android/build/.transforms/2892d280277a194daf04e3af971b529e/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/org/wonday/pdf/PdfView.dex +0 -0
- package/android/build/.transforms/2892d280277a194daf04e3af971b529e/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
- package/android/build/.transforms/e40f3b884607647e8beb6dabe8165962/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerDelegate.java +0 -30
- package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerInterface.java +0 -10
- package/android/build/generated/source/codegen/jni/react/renderer/components/rnpdf/Props.cpp +0 -35
- package/android/build/generated/source/codegen/jni/react/renderer/components/rnpdf/Props.h +0 -7
- package/android/build/generated/source/codegen/schema.json +1 -1
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/RNPDFPdfViewManagerDelegate.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/RNPDFPdfViewManagerInterface.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/wonday/pdf/PdfManager.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/wonday/pdf/PdfView$1.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/wonday/pdf/PdfView$2.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/wonday/pdf/PdfView$3.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/wonday/pdf/PdfView.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/RNPDFPdfViewManagerDelegate.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/RNPDFPdfViewManagerInterface.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/org/wonday/pdf/PdfManager.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/org/wonday/pdf/PdfView$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/org/wonday/pdf/PdfView$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/org/wonday/pdf/PdfView$3.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/org/wonday/pdf/PdfView.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/src/main/java/org/wonday/pdf/PdfManager.java +6 -63
- package/android/src/main/java/org/wonday/pdf/PdfView.java +4 -1189
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerDelegate.java +0 -30
- package/android/src/paper/java/com/facebook/react/viewmanagers/RNPDFPdfViewManagerInterface.java +0 -10
- package/fabric/RNPDFPdfNativeComponent.js +3 -18
- package/index.d.ts +1 -102
- package/index.js +0 -110
- package/index.js.flow +0 -72
- package/ios/RNPDFPdf/RNPDFPdfView.h +0 -11
- package/ios/RNPDFPdf/RNPDFPdfView.mm +0 -1242
- package/ios/RNPDFPdf/RNPDFPdfViewManager.mm +0 -37
- package/package.json +5 -6
- package/annotationDocumentUtils.js +0 -74
|
@@ -54,41 +54,6 @@
|
|
|
54
54
|
const float MAX_SCALE = 3.0f;
|
|
55
55
|
const float MIN_SCALE = 1.0f;
|
|
56
56
|
|
|
57
|
-
@class RNPDFAnnotationOverlay;
|
|
58
|
-
|
|
59
|
-
@interface RNPDFAnnotationOverlay : UIView <UITextViewDelegate>
|
|
60
|
-
@property(nonatomic, weak) PDFView *pdfView;
|
|
61
|
-
@property(nonatomic, weak) PDFDocument *pdfDocument;
|
|
62
|
-
@property(nonatomic, assign) BOOL annotationMode;
|
|
63
|
-
@property(nonatomic, assign) BOOL annotationEditable;
|
|
64
|
-
@property(nonatomic, copy) NSString *annotationTool;
|
|
65
|
-
@property(nonatomic, copy) NSString *annotationIdMode;
|
|
66
|
-
@property(nonatomic, copy) NSString *annotationInkColor;
|
|
67
|
-
@property(nonatomic, assign) CGFloat annotationInkThickness;
|
|
68
|
-
|
|
69
|
-
- (void)replaceAnnotationsJSONString:(NSString *)json editable:(BOOL)editable idMode:(NSString *)idMode;
|
|
70
|
-
- (void)setAnnotationMode:(BOOL)annotationMode tool:(NSString *)tool editable:(BOOL)editable idMode:(NSString *)idMode;
|
|
71
|
-
- (void)setInkDefaultsColor:(NSString *)color thickness:(CGFloat)thickness;
|
|
72
|
-
- (void)beginInkAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page;
|
|
73
|
-
- (void)appendInkPointAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page;
|
|
74
|
-
- (void)endInk;
|
|
75
|
-
- (void)beginMarkupAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page type:(NSString *)type;
|
|
76
|
-
- (void)updateMarkupAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page;
|
|
77
|
-
- (void)endMarkup;
|
|
78
|
-
- (void)createTextAnnotationAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page;
|
|
79
|
-
- (NSDictionary *)annotationSelectionHitAtPoint:(CGPoint)point includeHandles:(BOOL)includeHandles;
|
|
80
|
-
- (void)selectAnnotation:(NSDictionary *)annotation;
|
|
81
|
-
- (void)clearSelection;
|
|
82
|
-
- (void)deleteAnnotation:(NSDictionary *)annotation;
|
|
83
|
-
- (void)deleteSelectedAnnotation;
|
|
84
|
-
- (void)deleteAllAnnotations;
|
|
85
|
-
- (void)beginSelectionInteractionAtPoint:(CGPoint)point hit:(NSDictionary *)hit;
|
|
86
|
-
- (void)updateSelectionInteractionAtPoint:(CGPoint)point;
|
|
87
|
-
- (void)endSelectionInteraction;
|
|
88
|
-
- (void)commitTextEditingIfNeeded;
|
|
89
|
-
- (NSString *)serializedDocumentJSONStringWithEditable:(BOOL)editable idMode:(NSString *)idMode;
|
|
90
|
-
@end
|
|
91
|
-
|
|
92
57
|
@interface RNPDFPdfView() <PDFDocumentDelegate, PDFViewDelegate
|
|
93
58
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
94
59
|
, RCTRNPDFPdfViewViewProtocol
|
|
@@ -110,8 +75,6 @@ const float MIN_SCALE = 1.0f;
|
|
|
110
75
|
UIPinchGestureRecognizer *_pinchRecognizer;
|
|
111
76
|
UILongPressGestureRecognizer *_longPressRecognizer;
|
|
112
77
|
UITapGestureRecognizer *_doubleTapEmptyRecognizer;
|
|
113
|
-
UIPanGestureRecognizer *_annotationPanRecognizer;
|
|
114
|
-
RNPDFAnnotationOverlay *_annotationOverlay;
|
|
115
78
|
|
|
116
79
|
// Autoscroll
|
|
117
80
|
CADisplayLink *_displayLink;
|
|
@@ -194,34 +157,6 @@ using namespace facebook::react;
|
|
|
194
157
|
_enableDoubleTapZoom = newProps.enableDoubleTapZoom;
|
|
195
158
|
[updatedPropNames addObject:@"enableDoubleTapZoom"];
|
|
196
159
|
}
|
|
197
|
-
if (_annotations != RCTNSStringFromStringNilIfEmpty(newProps.annotations)) {
|
|
198
|
-
_annotations = RCTNSStringFromStringNilIfEmpty(newProps.annotations);
|
|
199
|
-
[updatedPropNames addObject:@"annotations"];
|
|
200
|
-
}
|
|
201
|
-
if (_annotationMode != newProps.annotationMode) {
|
|
202
|
-
_annotationMode = newProps.annotationMode;
|
|
203
|
-
[updatedPropNames addObject:@"annotationMode"];
|
|
204
|
-
}
|
|
205
|
-
if (_annotationTool != RCTNSStringFromStringNilIfEmpty(newProps.annotationTool)) {
|
|
206
|
-
_annotationTool = RCTNSStringFromStringNilIfEmpty(newProps.annotationTool);
|
|
207
|
-
[updatedPropNames addObject:@"annotationTool"];
|
|
208
|
-
}
|
|
209
|
-
if (_annotationEditable != newProps.annotationEditable) {
|
|
210
|
-
_annotationEditable = newProps.annotationEditable;
|
|
211
|
-
[updatedPropNames addObject:@"annotationEditable"];
|
|
212
|
-
}
|
|
213
|
-
if (_annotationIdMode != RCTNSStringFromStringNilIfEmpty(newProps.annotationIdMode)) {
|
|
214
|
-
_annotationIdMode = RCTNSStringFromStringNilIfEmpty(newProps.annotationIdMode);
|
|
215
|
-
[updatedPropNames addObject:@"annotationIdMode"];
|
|
216
|
-
}
|
|
217
|
-
if (_annotationInkColor != RCTNSStringFromStringNilIfEmpty(newProps.annotationInkColor)) {
|
|
218
|
-
_annotationInkColor = RCTNSStringFromStringNilIfEmpty(newProps.annotationInkColor);
|
|
219
|
-
[updatedPropNames addObject:@"annotationInkColor"];
|
|
220
|
-
}
|
|
221
|
-
if (_annotationInkThickness != newProps.annotationInkThickness) {
|
|
222
|
-
_annotationInkThickness = newProps.annotationInkThickness;
|
|
223
|
-
[updatedPropNames addObject:@"annotationInkThickness"];
|
|
224
|
-
}
|
|
225
160
|
if (_fitPolicy != newProps.fitPolicy) {
|
|
226
161
|
_fitPolicy = newProps.fitPolicy;
|
|
227
162
|
[updatedPropNames addObject:@"fitPolicy"];
|
|
@@ -254,14 +189,6 @@ using namespace facebook::react;
|
|
|
254
189
|
|
|
255
190
|
[super updateProps:props oldProps:oldProps];
|
|
256
191
|
[self didSetProps:updatedPropNames];
|
|
257
|
-
|
|
258
|
-
if (_annotationOverlay) {
|
|
259
|
-
[_annotationOverlay replaceAnnotationsJSONString:_annotations editable:_annotationEditable idMode:_annotationIdMode];
|
|
260
|
-
[_annotationOverlay setAnnotationMode:_annotationMode tool:_annotationTool editable:_annotationEditable idMode:_annotationIdMode];
|
|
261
|
-
[_annotationOverlay setInkDefaultsColor:_annotationInkColor thickness:_annotationInkThickness];
|
|
262
|
-
_annotationOverlay.pdfView = _pdfView;
|
|
263
|
-
_annotationOverlay.pdfDocument = _pdfDocument;
|
|
264
|
-
}
|
|
265
192
|
}
|
|
266
193
|
|
|
267
194
|
// already added in case https://github.com/facebook/react-native/pull/35378 has been merged
|
|
@@ -292,10 +219,6 @@ using namespace facebook::react;
|
|
|
292
219
|
[self removeGestureRecognizer:_pinchRecognizer];
|
|
293
220
|
[self removeGestureRecognizer:_longPressRecognizer];
|
|
294
221
|
[self removeGestureRecognizer:_doubleTapEmptyRecognizer];
|
|
295
|
-
[self removeGestureRecognizer:_annotationPanRecognizer];
|
|
296
|
-
|
|
297
|
-
[_annotationOverlay removeFromSuperview];
|
|
298
|
-
_annotationOverlay = nil;
|
|
299
222
|
|
|
300
223
|
[self initCommonProps];
|
|
301
224
|
}
|
|
@@ -305,7 +228,6 @@ using namespace facebook::react;
|
|
|
305
228
|
// Fabric equivalent of `reactSetFrame` method
|
|
306
229
|
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
|
|
307
230
|
_pdfView.frame = CGRectMake(0, 0, layoutMetrics.frame.size.width, layoutMetrics.frame.size.height);
|
|
308
|
-
_annotationOverlay.frame = CGRectMake(0, 0, layoutMetrics.frame.size.width, layoutMetrics.frame.size.height);
|
|
309
231
|
|
|
310
232
|
NSMutableArray *mProps = [_changedProps mutableCopy];
|
|
311
233
|
if (_initialed) {
|
|
@@ -367,8 +289,6 @@ using namespace facebook::react;
|
|
|
367
289
|
_showsHorizontalScrollIndicator = YES;
|
|
368
290
|
_showsVerticalScrollIndicator = YES;
|
|
369
291
|
_scrollEnabled = YES;
|
|
370
|
-
_annotationInkColor = @"#111111";
|
|
371
|
-
_annotationInkThickness = 2.0f;
|
|
372
292
|
_enableTextSelection = YES;
|
|
373
293
|
_selectedText = nil;
|
|
374
294
|
_currentPDFSelection = nil;
|
|
@@ -395,13 +315,6 @@ using namespace facebook::react;
|
|
|
395
315
|
_autoScrollCurrentOffset = 0.0;
|
|
396
316
|
|
|
397
317
|
[self addSubview:_pdfView];
|
|
398
|
-
_annotationOverlay = [[RNPDFAnnotationOverlay alloc] initWithFrame:self.bounds];
|
|
399
|
-
_annotationOverlay.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
400
|
-
_annotationOverlay.backgroundColor = UIColor.clearColor;
|
|
401
|
-
_annotationOverlay.userInteractionEnabled = YES;
|
|
402
|
-
[_annotationOverlay setInkDefaultsColor:_annotationInkColor thickness:_annotationInkThickness];
|
|
403
|
-
[self addSubview:_annotationOverlay];
|
|
404
|
-
[self bringSubviewToFront:_annotationOverlay];
|
|
405
318
|
|
|
406
319
|
|
|
407
320
|
// register notification
|
|
@@ -512,10 +425,6 @@ using namespace facebook::react;
|
|
|
512
425
|
}
|
|
513
426
|
|
|
514
427
|
_pdfView.document = _pdfDocument;
|
|
515
|
-
if (_annotationOverlay) {
|
|
516
|
-
_annotationOverlay.pdfView = _pdfView;
|
|
517
|
-
_annotationOverlay.pdfDocument = _pdfDocument;
|
|
518
|
-
}
|
|
519
428
|
} else {
|
|
520
429
|
|
|
521
430
|
[self notifyOnChangeWithMessage:[[NSString alloc] initWithString:[NSString stringWithFormat:@"error|Load pdf failed. path=%s",_path.UTF8String]]];
|
|
@@ -689,14 +598,6 @@ using namespace facebook::react;
|
|
|
689
598
|
}
|
|
690
599
|
}
|
|
691
600
|
|
|
692
|
-
if (_annotationOverlay) {
|
|
693
|
-
[_annotationOverlay replaceAnnotationsJSONString:_annotations editable:_annotationEditable idMode:_annotationIdMode];
|
|
694
|
-
[_annotationOverlay setAnnotationMode:_annotationMode tool:_annotationTool editable:_annotationEditable idMode:_annotationIdMode];
|
|
695
|
-
[_annotationOverlay setInkDefaultsColor:_annotationInkColor thickness:_annotationInkThickness];
|
|
696
|
-
_annotationOverlay.pdfView = _pdfView;
|
|
697
|
-
_annotationOverlay.pdfDocument = _pdfDocument;
|
|
698
|
-
}
|
|
699
|
-
|
|
700
601
|
_pdfView.backgroundColor = [UIColor clearColor];
|
|
701
602
|
[_pdfView layoutDocumentView];
|
|
702
603
|
[self setNeedsDisplay];
|
|
@@ -865,8 +766,6 @@ using namespace facebook::react;
|
|
|
865
766
|
[self notifyOnChangeWithMessage:[[NSString alloc] initWithString:[NSString stringWithFormat:@"pageChanged|%lu|%lu", page+1, numberOfPages]]];
|
|
866
767
|
}
|
|
867
768
|
|
|
868
|
-
[_annotationOverlay refreshDisplay];
|
|
869
|
-
|
|
870
769
|
}
|
|
871
770
|
|
|
872
771
|
- (void)onScaleChanged:(NSNotification *)noti
|
|
@@ -878,8 +777,6 @@ using namespace facebook::react;
|
|
|
878
777
|
[self notifyOnChangeWithMessage:[[NSString alloc] initWithString:[NSString stringWithFormat:@"scaleChanged|%f", _scale]]];
|
|
879
778
|
}
|
|
880
779
|
}
|
|
881
|
-
|
|
882
|
-
[_annotationOverlay refreshDisplay];
|
|
883
780
|
}
|
|
884
781
|
|
|
885
782
|
#pragma mark gesture process
|
|
@@ -978,30 +875,6 @@ using namespace facebook::react;
|
|
|
978
875
|
PDFPage *pdfPage = [_pdfView pageForPoint:point nearest:NO];
|
|
979
876
|
if (pdfPage) {
|
|
980
877
|
unsigned long page = [_pdfDocument indexForPage:pdfPage];
|
|
981
|
-
if (_annotationMode && _annotationEditable) {
|
|
982
|
-
if ([_annotationTool isEqualToString:@"select"]) {
|
|
983
|
-
[_annotationOverlay commitTextEditingIfNeeded];
|
|
984
|
-
|
|
985
|
-
NSDictionary *hit = [_annotationOverlay annotationSelectionHitAtPoint:point includeHandles:YES];
|
|
986
|
-
if (hit) {
|
|
987
|
-
NSDictionary *annotation = hit[@"annotation"];
|
|
988
|
-
[_annotationOverlay selectAnnotation:annotation];
|
|
989
|
-
|
|
990
|
-
return;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
[_annotationOverlay clearSelection];
|
|
994
|
-
[self notifyOnChangeWithMessage:
|
|
995
|
-
[[NSString alloc] initWithString:[NSString stringWithFormat:@"pageSingleTap|%lu|%f|%f", page+1, point.x, point.y]]];
|
|
996
|
-
return;
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
if ([_annotationTool isEqualToString:@"text"]) {
|
|
1000
|
-
[_annotationOverlay createTextAnnotationAtViewPoint:point page:pdfPage];
|
|
1001
|
-
return;
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
878
|
[self notifyOnChangeWithMessage:
|
|
1006
879
|
[[NSString alloc] initWithString:[NSString stringWithFormat:@"pageSingleTap|%lu|%f|%f", page+1, point.x, point.y]]];
|
|
1007
880
|
}
|
|
@@ -1031,86 +904,6 @@ using namespace facebook::react;
|
|
|
1031
904
|
|
|
1032
905
|
}
|
|
1033
906
|
|
|
1034
|
-
- (void)handleAnnotationPan:(UIPanGestureRecognizer *)sender
|
|
1035
|
-
{
|
|
1036
|
-
if (!_annotationMode || !_annotationEditable || _annotationTool == nil) {
|
|
1037
|
-
return;
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
CGPoint point = [sender locationInView:self];
|
|
1041
|
-
PDFPage *pdfPage = [_pdfDocument pageAtIndex:MAX(0, [_pdfDocument indexForPage:[_pdfView pageForPoint:point nearest:NO]])];
|
|
1042
|
-
if (!pdfPage) {
|
|
1043
|
-
return;
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
if ([_annotationTool isEqualToString:@"select"]) {
|
|
1047
|
-
if (sender.state == UIGestureRecognizerStateBegan) {
|
|
1048
|
-
[_annotationOverlay commitTextEditingIfNeeded];
|
|
1049
|
-
|
|
1050
|
-
NSDictionary *hit = [_annotationOverlay annotationSelectionHitAtPoint:point includeHandles:YES];
|
|
1051
|
-
if (!hit) {
|
|
1052
|
-
return;
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
[_annotationOverlay selectAnnotation:hit[@"annotation"]];
|
|
1056
|
-
[_annotationOverlay beginSelectionInteractionAtPoint:point hit:hit];
|
|
1057
|
-
} else if (sender.state == UIGestureRecognizerStateChanged) {
|
|
1058
|
-
[_annotationOverlay updateSelectionInteractionAtPoint:point];
|
|
1059
|
-
} else if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled || sender.state == UIGestureRecognizerStateFailed) {
|
|
1060
|
-
[_annotationOverlay endSelectionInteraction];
|
|
1061
|
-
}
|
|
1062
|
-
return;
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
if (sender.state == UIGestureRecognizerStateBegan) {
|
|
1066
|
-
if ([_annotationTool isEqualToString:@"ink"]) {
|
|
1067
|
-
[_annotationOverlay beginInkAtViewPoint:point page:pdfPage];
|
|
1068
|
-
} else if ([_annotationTool isEqualToString:@"highlight"]) {
|
|
1069
|
-
[_annotationOverlay beginMarkupAtViewPoint:point page:pdfPage type:_annotationTool];
|
|
1070
|
-
}
|
|
1071
|
-
} else if (sender.state == UIGestureRecognizerStateChanged) {
|
|
1072
|
-
if ([_annotationTool isEqualToString:@"ink"]) {
|
|
1073
|
-
[_annotationOverlay appendInkPointAtViewPoint:point page:pdfPage];
|
|
1074
|
-
} else if ([_annotationTool isEqualToString:@"highlight"]) {
|
|
1075
|
-
[_annotationOverlay updateMarkupAtViewPoint:point page:pdfPage];
|
|
1076
|
-
}
|
|
1077
|
-
} else if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled || sender.state == UIGestureRecognizerStateFailed) {
|
|
1078
|
-
if ([_annotationTool isEqualToString:@"ink"]) {
|
|
1079
|
-
[_annotationOverlay endInk];
|
|
1080
|
-
} else if ([_annotationTool isEqualToString:@"highlight"]) {
|
|
1081
|
-
[_annotationOverlay endMarkup];
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
- (void)saveAnnotations
|
|
1087
|
-
{
|
|
1088
|
-
if (_annotationOverlay) {
|
|
1089
|
-
[_annotationOverlay commitTextEditingIfNeeded];
|
|
1090
|
-
NSString *jsonString = [_annotationOverlay serializedDocumentJSONStringWithEditable:_annotationEditable idMode:_annotationIdMode];
|
|
1091
|
-
[self notifyOnChangeWithMessage:[NSString stringWithFormat:@"annotationSaveComplete|%@", jsonString]];
|
|
1092
|
-
return;
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
[self notifyOnChangeWithMessage:@"annotationSaveError|Annotation overlay unavailable"];
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
- (void)deleteSelectedAnnotation
|
|
1099
|
-
{
|
|
1100
|
-
if (_annotationOverlay) {
|
|
1101
|
-
[_annotationOverlay commitTextEditingIfNeeded];
|
|
1102
|
-
[_annotationOverlay deleteSelectedAnnotation];
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
- (void)deleteAllAnnotations
|
|
1107
|
-
{
|
|
1108
|
-
if (_annotationOverlay) {
|
|
1109
|
-
[_annotationOverlay commitTextEditingIfNeeded];
|
|
1110
|
-
[_annotationOverlay deleteAllAnnotations];
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
907
|
/**
|
|
1115
908
|
* Bind tap
|
|
1116
909
|
*
|
|
@@ -1157,15 +950,6 @@ using namespace facebook::react;
|
|
|
1157
950
|
[self addGestureRecognizer:longPressRecognizer];
|
|
1158
951
|
_longPressRecognizer = longPressRecognizer;
|
|
1159
952
|
|
|
1160
|
-
UIPanGestureRecognizer *annotationPanRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self
|
|
1161
|
-
action:@selector(handleAnnotationPan:)];
|
|
1162
|
-
annotationPanRecognizer.maximumNumberOfTouches = 1;
|
|
1163
|
-
annotationPanRecognizer.minimumNumberOfTouches = 1;
|
|
1164
|
-
annotationPanRecognizer.delegate = self;
|
|
1165
|
-
annotationPanRecognizer.cancelsTouchesInView = YES;
|
|
1166
|
-
[self addGestureRecognizer:annotationPanRecognizer];
|
|
1167
|
-
_annotationPanRecognizer = annotationPanRecognizer;
|
|
1168
|
-
|
|
1169
953
|
// Override the _pdfView double tap gesture recognizer so that it doesn't confilict with custom double tap
|
|
1170
954
|
UITapGestureRecognizer *doubleTapEmptyRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
|
|
1171
955
|
action:@selector(handleDoubleTapEmpty:)];
|
|
@@ -1177,28 +961,11 @@ using namespace facebook::react;
|
|
|
1177
961
|
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
|
|
1178
962
|
|
|
1179
963
|
{
|
|
1180
|
-
if (gestureRecognizer == _annotationPanRecognizer) {
|
|
1181
|
-
if (!_annotationMode || !_annotationEditable || _annotationTool == nil) {
|
|
1182
|
-
return NO;
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
if ([_annotationTool isEqualToString:@"select"]) {
|
|
1186
|
-
CGPoint point = [gestureRecognizer locationInView:self];
|
|
1187
|
-
return [_annotationOverlay annotationSelectionHitAtPoint:point includeHandles:YES] != nil;
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
return [@[@"ink", @"highlight"] containsObject:_annotationTool];
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
964
|
return !_singlePage;
|
|
1194
965
|
}
|
|
1195
966
|
|
|
1196
967
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
|
1197
968
|
{
|
|
1198
|
-
if (gestureRecognizer == _annotationPanRecognizer || otherGestureRecognizer == _annotationPanRecognizer) {
|
|
1199
|
-
return NO;
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
969
|
return !_singlePage;
|
|
1203
970
|
}
|
|
1204
971
|
|
|
@@ -1370,1015 +1137,6 @@ using namespace facebook::react;
|
|
|
1370
1137
|
if ([_originalScrollDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
|
|
1371
1138
|
[_originalScrollDelegate scrollViewDidScroll:scrollView];
|
|
1372
1139
|
}
|
|
1373
|
-
|
|
1374
|
-
[_annotationOverlay refreshDisplay];
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
@end
|
|
1378
|
-
|
|
1379
|
-
static UIColor *RNPDFColorFromHexString(NSString *hexString, UIColor *fallback)
|
|
1380
|
-
{
|
|
1381
|
-
if (![hexString isKindOfClass:[NSString class]] || hexString.length == 0) {
|
|
1382
|
-
return fallback;
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
NSString *cleanHex = [[hexString stringByReplacingOccurrencesOfString:@"#" withString:@""] uppercaseString];
|
|
1386
|
-
unsigned int rgbValue = 0;
|
|
1387
|
-
if (cleanHex.length == 6) {
|
|
1388
|
-
NSScanner *scanner = [NSScanner scannerWithString:cleanHex];
|
|
1389
|
-
[scanner scanHexInt:&rgbValue];
|
|
1390
|
-
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16) / 255.0f
|
|
1391
|
-
green:((rgbValue & 0x00FF00) >> 8) / 255.0f
|
|
1392
|
-
blue:(rgbValue & 0x0000FF) / 255.0f
|
|
1393
|
-
alpha:1.0f];
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
if (cleanHex.length == 8) {
|
|
1397
|
-
NSScanner *scanner = [NSScanner scannerWithString:cleanHex];
|
|
1398
|
-
[scanner scanHexInt:&rgbValue];
|
|
1399
|
-
return [UIColor colorWithRed:((rgbValue & 0x00FF0000) >> 16) / 255.0f
|
|
1400
|
-
green:((rgbValue & 0x0000FF00) >> 8) / 255.0f
|
|
1401
|
-
blue:(rgbValue & 0x000000FF) / 255.0f
|
|
1402
|
-
alpha:((rgbValue & 0xFF000000) >> 24) / 255.0f];
|
|
1403
|
-
}
|
|
1404
|
-
|
|
1405
|
-
return fallback;
|
|
1406
|
-
}
|
|
1407
|
-
|
|
1408
|
-
static NSString *RNPDFGenerateAnnotationId(void)
|
|
1409
|
-
{
|
|
1410
|
-
return [[NSUUID UUID] UUIDString];
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
@implementation RNPDFAnnotationOverlay
|
|
1414
|
-
{
|
|
1415
|
-
NSMutableArray<NSMutableDictionary *> *_draftAnnotations;
|
|
1416
|
-
NSMutableDictionary *_activeInkAnnotation;
|
|
1417
|
-
NSMutableDictionary *_activeMarkupAnnotation;
|
|
1418
|
-
NSMutableDictionary *_activeTextAnnotation;
|
|
1419
|
-
NSString *_selectedAnnotationId;
|
|
1420
|
-
NSMutableDictionary *_activeSelectionAnnotation;
|
|
1421
|
-
NSString *_activeSelectionMode;
|
|
1422
|
-
NSString *_activeSelectionHandle;
|
|
1423
|
-
CGPoint _selectionStartPoint;
|
|
1424
|
-
CGRect _selectionStartBounds;
|
|
1425
|
-
NSArray *_selectionStartPoints;
|
|
1426
|
-
NSInteger _selectionPageIndex;
|
|
1427
|
-
CGPoint _activeMarkupStartNormalized;
|
|
1428
|
-
UITextView *_activeTextView;
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
- (instancetype)initWithFrame:(CGRect)frame
|
|
1432
|
-
{
|
|
1433
|
-
if (self = [super initWithFrame:frame]) {
|
|
1434
|
-
_draftAnnotations = [NSMutableArray new];
|
|
1435
|
-
_annotationMode = NO;
|
|
1436
|
-
_annotationEditable = YES;
|
|
1437
|
-
_annotationTool = @"select";
|
|
1438
|
-
_annotationIdMode = @"auto";
|
|
1439
|
-
_annotationInkColor = @"#111111";
|
|
1440
|
-
_annotationInkThickness = 2.0f;
|
|
1441
|
-
self.backgroundColor = UIColor.clearColor;
|
|
1442
|
-
self.opaque = NO;
|
|
1443
|
-
}
|
|
1444
|
-
return self;
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
- (void)setPdfView:(PDFView *)pdfView
|
|
1448
|
-
{
|
|
1449
|
-
_pdfView = pdfView;
|
|
1450
|
-
[self refreshDisplay];
|
|
1451
|
-
}
|
|
1452
|
-
|
|
1453
|
-
- (void)setPdfDocument:(PDFDocument *)pdfDocument
|
|
1454
|
-
{
|
|
1455
|
-
_pdfDocument = pdfDocument;
|
|
1456
|
-
[self refreshDisplay];
|
|
1457
|
-
}
|
|
1458
|
-
|
|
1459
|
-
- (void)replaceAnnotationsJSONString:(NSString *)json editable:(BOOL)editable idMode:(NSString *)idMode
|
|
1460
|
-
{
|
|
1461
|
-
self.annotationEditable = editable;
|
|
1462
|
-
self.annotationIdMode = idMode ?: @"auto";
|
|
1463
|
-
|
|
1464
|
-
NSArray *parsedAnnotations = [self parseAnnotationsFromJSONString:json];
|
|
1465
|
-
_draftAnnotations = [parsedAnnotations mutableCopy] ?: [NSMutableArray new];
|
|
1466
|
-
|
|
1467
|
-
[self commitTextEditingIfNeeded];
|
|
1468
|
-
[self refreshDisplay];
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
- (void)setAnnotationMode:(BOOL)annotationMode tool:(NSString *)tool editable:(BOOL)editable idMode:(NSString *)idMode
|
|
1472
|
-
{
|
|
1473
|
-
_annotationMode = annotationMode;
|
|
1474
|
-
_annotationEditable = editable;
|
|
1475
|
-
_annotationTool = [self normalizedAnnotationType:(tool ?: @"select")];
|
|
1476
|
-
_annotationIdMode = idMode ?: @"auto";
|
|
1477
|
-
|
|
1478
|
-
if (!annotationMode) {
|
|
1479
|
-
[self commitTextEditingIfNeeded];
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
- (void)setInkDefaultsColor:(NSString *)color thickness:(CGFloat)thickness
|
|
1484
|
-
{
|
|
1485
|
-
_annotationInkColor = color.length > 0 ? color : @"#111111";
|
|
1486
|
-
_annotationInkThickness = thickness > 0 ? thickness : 2.0f;
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
|
-
- (NSString *)normalizedAnnotationType:(NSString *)type
|
|
1490
|
-
{
|
|
1491
|
-
if ([type isEqualToString:@"underline"] || [type isEqualToString:@"strikeout"]) {
|
|
1492
|
-
return @"highlight";
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
return type;
|
|
1496
|
-
}
|
|
1497
|
-
|
|
1498
|
-
- (BOOL)annotationSupportsResize:(NSDictionary *)annotation
|
|
1499
|
-
{
|
|
1500
|
-
NSString *type = [self normalizedAnnotationType:annotation[@"type"]];
|
|
1501
|
-
return [type isEqualToString:@"text"] || [type isEqualToString:@"highlight"];
|
|
1502
|
-
}
|
|
1503
|
-
|
|
1504
|
-
- (NSArray *)parseAnnotationsFromJSONString:(NSString *)json
|
|
1505
|
-
{
|
|
1506
|
-
if (![json isKindOfClass:[NSString class]] || json.length == 0) {
|
|
1507
|
-
return @[];
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding];
|
|
1511
|
-
if (!data) {
|
|
1512
|
-
return @[];
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
NSError *error = nil;
|
|
1516
|
-
id parsed = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
|
|
1517
|
-
if (error || !parsed) {
|
|
1518
|
-
return @[];
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
NSArray *items = nil;
|
|
1522
|
-
if ([parsed isKindOfClass:[NSDictionary class]]) {
|
|
1523
|
-
id candidate = parsed[@"annotations"];
|
|
1524
|
-
if ([candidate isKindOfClass:[NSArray class]]) {
|
|
1525
|
-
items = candidate;
|
|
1526
|
-
}
|
|
1527
|
-
} else if ([parsed isKindOfClass:[NSArray class]]) {
|
|
1528
|
-
items = parsed;
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
|
-
if (![items isKindOfClass:[NSArray class]]) {
|
|
1532
|
-
return @[];
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
NSMutableArray *normalized = [NSMutableArray arrayWithCapacity:items.count];
|
|
1536
|
-
for (id item in items) {
|
|
1537
|
-
if (![item isKindOfClass:[NSDictionary class]]) {
|
|
1538
|
-
continue;
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1541
|
-
NSMutableDictionary *annotation = [item mutableCopy];
|
|
1542
|
-
NSString *type = [self normalizedAnnotationType:annotation[@"type"]];
|
|
1543
|
-
if (type.length > 0) {
|
|
1544
|
-
annotation[@"type"] = type;
|
|
1545
|
-
}
|
|
1546
|
-
if (!annotation[@"id"]) {
|
|
1547
|
-
annotation[@"id"] = RNPDFGenerateAnnotationId();
|
|
1548
|
-
}
|
|
1549
|
-
if (!annotation[@"page"]) {
|
|
1550
|
-
annotation[@"page"] = @(1);
|
|
1551
|
-
}
|
|
1552
|
-
[normalized addObject:annotation];
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
|
-
return normalized;
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
|
-
- (NSString *)serializedDocumentJSONStringWithEditable:(BOOL)editable idMode:(NSString *)idMode
|
|
1559
|
-
{
|
|
1560
|
-
NSMutableDictionary *document = [NSMutableDictionary dictionary];
|
|
1561
|
-
document[@"editable"] = @(editable);
|
|
1562
|
-
document[@"idMode"] = idMode ?: @"auto";
|
|
1563
|
-
document[@"annotations"] = [_draftAnnotations copy] ?: @[];
|
|
1564
|
-
|
|
1565
|
-
NSError *error = nil;
|
|
1566
|
-
NSData *data = [NSJSONSerialization dataWithJSONObject:document options:0 error:&error];
|
|
1567
|
-
if (error || !data) {
|
|
1568
|
-
return @"{}";
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ?: @"{}";
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
- (void)refreshDisplay
|
|
1575
|
-
{
|
|
1576
|
-
[self setNeedsDisplay];
|
|
1577
|
-
[self updateActiveTextEditorFrame];
|
|
1578
|
-
}
|
|
1579
|
-
|
|
1580
|
-
- (BOOL)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
|
1581
|
-
{
|
|
1582
|
-
if (_activeTextView) {
|
|
1583
|
-
if (CGRectContainsPoint(_activeTextView.frame, point)) {
|
|
1584
|
-
return _activeTextView;
|
|
1585
|
-
}
|
|
1586
|
-
|
|
1587
|
-
return self;
|
|
1588
|
-
}
|
|
1589
|
-
|
|
1590
|
-
return nil;
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
|
|
1594
|
-
{
|
|
1595
|
-
if (_activeTextView) {
|
|
1596
|
-
[self commitTextEditingIfNeeded];
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
|
-
[super touchesBegan:touches withEvent:event];
|
|
1600
|
-
}
|
|
1601
|
-
|
|
1602
|
-
- (void)layoutSubviews
|
|
1603
|
-
{
|
|
1604
|
-
[super layoutSubviews];
|
|
1605
|
-
[self updateActiveTextEditorFrame];
|
|
1606
|
-
}
|
|
1607
|
-
|
|
1608
|
-
- (CGPoint)normalizedPointForViewPoint:(CGPoint)viewPoint page:(PDFPage *)page
|
|
1609
|
-
{
|
|
1610
|
-
if (!self.pdfView || !page) {
|
|
1611
|
-
return CGPointZero;
|
|
1612
|
-
}
|
|
1613
|
-
|
|
1614
|
-
CGPoint pagePoint = [self.pdfView convertPoint:viewPoint toPage:page];
|
|
1615
|
-
CGRect pageBounds = [page boundsForBox:kPDFDisplayBoxCropBox];
|
|
1616
|
-
if (page.rotation == 90 || page.rotation == 270) {
|
|
1617
|
-
pageBounds = CGRectMake(0, 0, pageBounds.size.height, pageBounds.size.width);
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
CGFloat width = MAX(pageBounds.size.width, 1.0f);
|
|
1621
|
-
CGFloat height = MAX(pageBounds.size.height, 1.0f);
|
|
1622
|
-
return CGPointMake(pagePoint.x / width, 1.0f - (pagePoint.y / height));
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
- (CGPoint)viewPointForNormalizedPoint:(CGPoint)normalizedPoint page:(PDFPage *)page
|
|
1626
|
-
{
|
|
1627
|
-
if (!self.pdfView || !page) {
|
|
1628
|
-
return CGPointZero;
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
|
-
CGRect pageBounds = [page boundsForBox:kPDFDisplayBoxCropBox];
|
|
1632
|
-
if (page.rotation == 90 || page.rotation == 270) {
|
|
1633
|
-
pageBounds = CGRectMake(0, 0, pageBounds.size.height, pageBounds.size.width);
|
|
1634
|
-
}
|
|
1635
|
-
|
|
1636
|
-
CGFloat width = MAX(pageBounds.size.width, 1.0f);
|
|
1637
|
-
CGFloat height = MAX(pageBounds.size.height, 1.0f);
|
|
1638
|
-
CGPoint pagePoint = CGPointMake(normalizedPoint.x * width, (1.0f - normalizedPoint.y) * height);
|
|
1639
|
-
return [self.pdfView convertPoint:pagePoint fromPage:page];
|
|
1640
|
-
}
|
|
1641
|
-
|
|
1642
|
-
- (CGRect)viewRectForNormalizedBounds:(NSDictionary *)bounds page:(PDFPage *)page
|
|
1643
|
-
{
|
|
1644
|
-
if (!bounds || !page) {
|
|
1645
|
-
return CGRectZero;
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
|
-
CGFloat x = [bounds[@"x"] doubleValue];
|
|
1649
|
-
CGFloat y = [bounds[@"y"] doubleValue];
|
|
1650
|
-
CGFloat width = [bounds[@"width"] doubleValue];
|
|
1651
|
-
CGFloat height = [bounds[@"height"] doubleValue];
|
|
1652
|
-
|
|
1653
|
-
CGPoint topLeft = [self viewPointForNormalizedPoint:CGPointMake(x, y) page:page];
|
|
1654
|
-
CGPoint topRight = [self viewPointForNormalizedPoint:CGPointMake(x + width, y) page:page];
|
|
1655
|
-
CGPoint bottomLeft = [self viewPointForNormalizedPoint:CGPointMake(x, y + height) page:page];
|
|
1656
|
-
CGPoint bottomRight = [self viewPointForNormalizedPoint:CGPointMake(x + width, y + height) page:page];
|
|
1657
|
-
|
|
1658
|
-
CGFloat minX = MIN(MIN(topLeft.x, topRight.x), MIN(bottomLeft.x, bottomRight.x));
|
|
1659
|
-
CGFloat maxX = MAX(MAX(topLeft.x, topRight.x), MAX(bottomLeft.x, bottomRight.x));
|
|
1660
|
-
CGFloat minY = MIN(MIN(topLeft.y, topRight.y), MIN(bottomLeft.y, bottomRight.y));
|
|
1661
|
-
CGFloat maxY = MAX(MAX(topLeft.y, topRight.y), MAX(bottomLeft.y, bottomRight.y));
|
|
1662
|
-
|
|
1663
|
-
return CGRectMake(minX, minY, MAX(maxX - minX, 1.0f), MAX(maxY - minY, 1.0f));
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
- (CGRect)viewRectForAnnotation:(NSDictionary *)annotation page:(PDFPage *)page
|
|
1667
|
-
{
|
|
1668
|
-
if (!annotation || !page) {
|
|
1669
|
-
return CGRectZero;
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
|
-
NSString *type = annotation[@"type"];
|
|
1673
|
-
if ([type isEqualToString:@"ink"]) {
|
|
1674
|
-
NSArray *points = annotation[@"points"];
|
|
1675
|
-
if (![points isKindOfClass:[NSArray class]] || points.count == 0) {
|
|
1676
|
-
return CGRectZero;
|
|
1677
|
-
}
|
|
1678
|
-
|
|
1679
|
-
CGFloat minX = CGFLOAT_MAX;
|
|
1680
|
-
CGFloat minY = CGFLOAT_MAX;
|
|
1681
|
-
CGFloat maxX = -CGFLOAT_MAX;
|
|
1682
|
-
CGFloat maxY = -CGFLOAT_MAX;
|
|
1683
|
-
|
|
1684
|
-
for (NSDictionary *point in points) {
|
|
1685
|
-
if (![point isKindOfClass:[NSDictionary class]]) {
|
|
1686
|
-
continue;
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
|
-
CGPoint viewPoint = [self viewPointForNormalizedPoint:CGPointMake([point[@"x"] doubleValue], [point[@"y"] doubleValue]) page:page];
|
|
1690
|
-
minX = MIN(minX, viewPoint.x);
|
|
1691
|
-
minY = MIN(minY, viewPoint.y);
|
|
1692
|
-
maxX = MAX(maxX, viewPoint.x);
|
|
1693
|
-
maxY = MAX(maxY, viewPoint.y);
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
if (minX == CGFLOAT_MAX || minY == CGFLOAT_MAX || maxX == -CGFLOAT_MAX || maxY == -CGFLOAT_MAX) {
|
|
1697
|
-
return CGRectZero;
|
|
1698
|
-
}
|
|
1699
|
-
|
|
1700
|
-
return CGRectMake(minX, minY, MAX(maxX - minX, 1.0f), MAX(maxY - minY, 1.0f));
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
NSDictionary *bounds = annotation[@"bounds"];
|
|
1704
|
-
return [self viewRectForNormalizedBounds:bounds page:page];
|
|
1705
|
-
}
|
|
1706
|
-
|
|
1707
|
-
- (CGRect)normalizedBoundsForAnnotation:(NSDictionary *)annotation
|
|
1708
|
-
{
|
|
1709
|
-
if (!annotation) {
|
|
1710
|
-
return CGRectZero;
|
|
1711
|
-
}
|
|
1712
|
-
|
|
1713
|
-
NSString *type = annotation[@"type"];
|
|
1714
|
-
if ([type isEqualToString:@"ink"]) {
|
|
1715
|
-
NSArray *points = annotation[@"points"];
|
|
1716
|
-
if (![points isKindOfClass:[NSArray class]] || points.count == 0) {
|
|
1717
|
-
return CGRectZero;
|
|
1718
|
-
}
|
|
1719
|
-
|
|
1720
|
-
CGFloat minX = CGFLOAT_MAX;
|
|
1721
|
-
CGFloat minY = CGFLOAT_MAX;
|
|
1722
|
-
CGFloat maxX = -CGFLOAT_MAX;
|
|
1723
|
-
CGFloat maxY = -CGFLOAT_MAX;
|
|
1724
|
-
|
|
1725
|
-
for (NSDictionary *point in points) {
|
|
1726
|
-
if (![point isKindOfClass:[NSDictionary class]]) {
|
|
1727
|
-
continue;
|
|
1728
|
-
}
|
|
1729
|
-
|
|
1730
|
-
CGFloat x = [point[@"x"] doubleValue];
|
|
1731
|
-
CGFloat y = [point[@"y"] doubleValue];
|
|
1732
|
-
minX = MIN(minX, x);
|
|
1733
|
-
minY = MIN(minY, y);
|
|
1734
|
-
maxX = MAX(maxX, x);
|
|
1735
|
-
maxY = MAX(maxY, y);
|
|
1736
|
-
}
|
|
1737
|
-
|
|
1738
|
-
if (minX == CGFLOAT_MAX || minY == CGFLOAT_MAX || maxX == -CGFLOAT_MAX || maxY == -CGFLOAT_MAX) {
|
|
1739
|
-
return CGRectZero;
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
return CGRectMake(minX, minY, MAX(maxX - minX, 0.001f), MAX(maxY - minY, 0.001f));
|
|
1743
|
-
}
|
|
1744
|
-
|
|
1745
|
-
NSDictionary *bounds = annotation[@"bounds"];
|
|
1746
|
-
if (![bounds isKindOfClass:[NSDictionary class]]) {
|
|
1747
|
-
return CGRectZero;
|
|
1748
|
-
}
|
|
1749
|
-
|
|
1750
|
-
CGFloat x = [bounds[@"x"] doubleValue];
|
|
1751
|
-
CGFloat y = [bounds[@"y"] doubleValue];
|
|
1752
|
-
CGFloat width = [bounds[@"width"] doubleValue];
|
|
1753
|
-
CGFloat height = [bounds[@"height"] doubleValue];
|
|
1754
|
-
return CGRectMake(x, y, MAX(width, 0.001f), MAX(height, 0.001f));
|
|
1755
|
-
}
|
|
1756
|
-
|
|
1757
|
-
- (NSArray *)copyPointsForAnnotation:(NSDictionary *)annotation
|
|
1758
|
-
{
|
|
1759
|
-
if (![annotation[@"type"] isEqualToString:@"ink"]) {
|
|
1760
|
-
return nil;
|
|
1761
|
-
}
|
|
1762
|
-
|
|
1763
|
-
NSArray *points = annotation[@"points"];
|
|
1764
|
-
if (![points isKindOfClass:[NSArray class]]) {
|
|
1765
|
-
return nil;
|
|
1766
|
-
}
|
|
1767
|
-
|
|
1768
|
-
return [points copy];
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
- (NSDictionary *)selectedAnnotation
|
|
1772
|
-
{
|
|
1773
|
-
if (_selectedAnnotationId.length == 0) {
|
|
1774
|
-
return nil;
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
for (NSDictionary *annotation in [_draftAnnotations reverseObjectEnumerator]) {
|
|
1778
|
-
if ([_selectedAnnotationId isEqualToString:annotation[@"id"]]) {
|
|
1779
|
-
return annotation;
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
|
|
1783
|
-
return nil;
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
- (CGRect)resizeHandleRectForRect:(CGRect)rect
|
|
1787
|
-
{
|
|
1788
|
-
CGFloat size = MAX(16.0f, MIN(rect.size.width, rect.size.height) * 0.18f);
|
|
1789
|
-
return CGRectMake(CGRectGetMaxX(rect) - size, CGRectGetMaxY(rect) - size, size, size);
|
|
1790
|
-
}
|
|
1791
|
-
|
|
1792
|
-
- (NSDictionary *)annotationSelectionHitAtPoint:(CGPoint)point includeHandles:(BOOL)includeHandles
|
|
1793
|
-
{
|
|
1794
|
-
if (!self.pdfDocument || _draftAnnotations.count == 0) {
|
|
1795
|
-
return nil;
|
|
1796
|
-
}
|
|
1797
|
-
|
|
1798
|
-
PDFPage *page = [self.pdfView pageForPoint:point nearest:NO];
|
|
1799
|
-
if (!page) {
|
|
1800
|
-
return nil;
|
|
1801
|
-
}
|
|
1802
|
-
|
|
1803
|
-
NSInteger pageIndex = [self.pdfDocument indexForPage:page];
|
|
1804
|
-
for (NSDictionary *annotation in [_draftAnnotations reverseObjectEnumerator]) {
|
|
1805
|
-
NSNumber *annotationPageNumber = annotation[@"page"];
|
|
1806
|
-
if (!annotationPageNumber || annotationPageNumber.integerValue - 1 != pageIndex) {
|
|
1807
|
-
continue;
|
|
1808
|
-
}
|
|
1809
|
-
|
|
1810
|
-
CGRect rect = [self viewRectForAnnotation:annotation page:page];
|
|
1811
|
-
if (CGRectIsEmpty(rect)) {
|
|
1812
|
-
continue;
|
|
1813
|
-
}
|
|
1814
|
-
|
|
1815
|
-
CGRect hitRect = CGRectInset(rect, -12.0f, -12.0f);
|
|
1816
|
-
if (!CGRectContainsPoint(hitRect, point)) {
|
|
1817
|
-
continue;
|
|
1818
|
-
}
|
|
1819
|
-
|
|
1820
|
-
NSString *hitPart = @"body";
|
|
1821
|
-
if (includeHandles && [_selectedAnnotationId isEqualToString:annotation[@"id"]] && [self annotationSupportsResize:annotation] && CGRectContainsPoint([self resizeHandleRectForRect:rect], point)) {
|
|
1822
|
-
hitPart = @"resize";
|
|
1823
|
-
}
|
|
1824
|
-
|
|
1825
|
-
return @{@"annotation": annotation,
|
|
1826
|
-
@"pageIndex": @(pageIndex),
|
|
1827
|
-
@"hitPart": hitPart,
|
|
1828
|
-
@"rect": [NSValue valueWithCGRect:rect]};
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
return nil;
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
|
-
- (void)selectAnnotation:(NSDictionary *)annotation
|
|
1835
|
-
{
|
|
1836
|
-
_selectedAnnotationId = [annotation[@"id"] copy];
|
|
1837
|
-
[self refreshDisplay];
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
- (void)clearSelection
|
|
1841
|
-
{
|
|
1842
|
-
_selectedAnnotationId = nil;
|
|
1843
|
-
[self refreshDisplay];
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
|
-
- (void)deleteAnnotation:(NSDictionary *)annotation
|
|
1847
|
-
{
|
|
1848
|
-
if (!annotation) {
|
|
1849
|
-
return;
|
|
1850
|
-
}
|
|
1851
|
-
|
|
1852
|
-
[self commitTextEditingIfNeeded];
|
|
1853
|
-
|
|
1854
|
-
NSString *annotationId = annotation[@"id"];
|
|
1855
|
-
if (annotationId.length == 0) {
|
|
1856
|
-
return;
|
|
1857
|
-
}
|
|
1858
|
-
|
|
1859
|
-
NSUInteger removeIndex = NSNotFound;
|
|
1860
|
-
for (NSUInteger index = 0; index < _draftAnnotations.count; index++) {
|
|
1861
|
-
NSDictionary *candidate = _draftAnnotations[index];
|
|
1862
|
-
if ([annotationId isEqualToString:candidate[@"id"]]) {
|
|
1863
|
-
removeIndex = index;
|
|
1864
|
-
break;
|
|
1865
|
-
}
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
if (removeIndex != NSNotFound) {
|
|
1869
|
-
[_draftAnnotations removeObjectAtIndex:removeIndex];
|
|
1870
|
-
}
|
|
1871
|
-
|
|
1872
|
-
if ([_selectedAnnotationId isEqualToString:annotationId]) {
|
|
1873
|
-
_selectedAnnotationId = nil;
|
|
1874
|
-
}
|
|
1875
|
-
|
|
1876
|
-
[self endSelectionInteraction];
|
|
1877
|
-
|
|
1878
|
-
[self refreshDisplay];
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1881
|
-
- (void)deleteSelectedAnnotation
|
|
1882
|
-
{
|
|
1883
|
-
NSDictionary *annotation = [self selectedAnnotation];
|
|
1884
|
-
if (annotation) {
|
|
1885
|
-
[self deleteAnnotation:annotation];
|
|
1886
|
-
}
|
|
1887
|
-
}
|
|
1888
|
-
|
|
1889
|
-
- (void)deleteAllAnnotations
|
|
1890
|
-
{
|
|
1891
|
-
[self commitTextEditingIfNeeded];
|
|
1892
|
-
[_draftAnnotations removeAllObjects];
|
|
1893
|
-
_selectedAnnotationId = nil;
|
|
1894
|
-
[self endSelectionInteraction];
|
|
1895
|
-
[self refreshDisplay];
|
|
1896
|
-
}
|
|
1897
|
-
|
|
1898
|
-
- (void)beginSelectionInteractionAtPoint:(CGPoint)point hit:(NSDictionary *)hit
|
|
1899
|
-
{
|
|
1900
|
-
NSDictionary *annotation = hit[@"annotation"];
|
|
1901
|
-
if (![annotation isKindOfClass:[NSDictionary class]]) {
|
|
1902
|
-
return;
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
|
-
_activeSelectionAnnotation = (NSMutableDictionary *)annotation;
|
|
1906
|
-
_activeSelectionMode = [hit[@"hitPart"] isEqualToString:@"resize"] ? @"resize" : @"move";
|
|
1907
|
-
_activeSelectionHandle = hit[@"hitPart"] ?: @"body";
|
|
1908
|
-
_selectionStartPoint = point;
|
|
1909
|
-
_selectionPageIndex = [hit[@"pageIndex"] integerValue];
|
|
1910
|
-
_selectionStartBounds = [self normalizedBoundsForAnnotation:annotation];
|
|
1911
|
-
_selectionStartPoints = [self copyPointsForAnnotation:annotation];
|
|
1912
|
-
}
|
|
1913
|
-
|
|
1914
|
-
- (void)updateSelectionInteractionAtPoint:(CGPoint)point
|
|
1915
|
-
{
|
|
1916
|
-
if (!_activeSelectionAnnotation || _selectionPageIndex < 0 || !_pdfDocument || _selectionPageIndex >= _pdfDocument.pageCount) {
|
|
1917
|
-
return;
|
|
1918
|
-
}
|
|
1919
|
-
|
|
1920
|
-
PDFPage *page = [_pdfDocument pageAtIndex:_selectionPageIndex];
|
|
1921
|
-
if (!page) {
|
|
1922
|
-
return;
|
|
1923
|
-
}
|
|
1924
|
-
|
|
1925
|
-
CGPoint startNormalized = [self normalizedPointForViewPoint:_selectionStartPoint page:page];
|
|
1926
|
-
CGPoint currentNormalized = [self normalizedPointForViewPoint:point page:page];
|
|
1927
|
-
CGFloat deltaX = currentNormalized.x - startNormalized.x;
|
|
1928
|
-
CGFloat deltaY = currentNormalized.y - startNormalized.y;
|
|
1929
|
-
|
|
1930
|
-
CGRect newBounds = _selectionStartBounds;
|
|
1931
|
-
if ([_activeSelectionMode isEqualToString:@"resize"]) {
|
|
1932
|
-
newBounds.size.width = MAX(0.01f, _selectionStartBounds.size.width + deltaX);
|
|
1933
|
-
newBounds.size.height = MAX(0.01f, _selectionStartBounds.size.height + deltaY);
|
|
1934
|
-
} else {
|
|
1935
|
-
newBounds.origin.x = _selectionStartBounds.origin.x + deltaX;
|
|
1936
|
-
newBounds.origin.y = _selectionStartBounds.origin.y + deltaY;
|
|
1937
|
-
}
|
|
1938
|
-
|
|
1939
|
-
[self applySelectionBounds:newBounds toAnnotation:_activeSelectionAnnotation startBounds:_selectionStartBounds startPoints:_selectionStartPoints];
|
|
1940
|
-
[self refreshDisplay];
|
|
1941
|
-
}
|
|
1942
|
-
|
|
1943
|
-
- (void)endSelectionInteraction
|
|
1944
|
-
{
|
|
1945
|
-
_activeSelectionAnnotation = nil;
|
|
1946
|
-
_activeSelectionMode = nil;
|
|
1947
|
-
_activeSelectionHandle = nil;
|
|
1948
|
-
_selectionStartPoints = nil;
|
|
1949
|
-
_selectionPageIndex = -1;
|
|
1950
|
-
}
|
|
1951
|
-
|
|
1952
|
-
- (void)applySelectionBounds:(CGRect)newBounds toAnnotation:(NSMutableDictionary *)annotation startBounds:(CGRect)startBounds startPoints:(NSArray *)startPoints
|
|
1953
|
-
{
|
|
1954
|
-
if (!annotation) {
|
|
1955
|
-
return;
|
|
1956
|
-
}
|
|
1957
|
-
|
|
1958
|
-
NSString *type = annotation[@"type"];
|
|
1959
|
-
if ([type isEqualToString:@"ink"]) {
|
|
1960
|
-
if (![startPoints isKindOfClass:[NSArray class]]) {
|
|
1961
|
-
return;
|
|
1962
|
-
}
|
|
1963
|
-
|
|
1964
|
-
CGFloat startWidth = MAX(startBounds.size.width, 0.001f);
|
|
1965
|
-
CGFloat startHeight = MAX(startBounds.size.height, 0.001f);
|
|
1966
|
-
CGFloat newWidth = MAX(newBounds.size.width, 0.001f);
|
|
1967
|
-
CGFloat newHeight = MAX(newBounds.size.height, 0.001f);
|
|
1968
|
-
|
|
1969
|
-
NSMutableArray *transformedPoints = [NSMutableArray arrayWithCapacity:startPoints.count];
|
|
1970
|
-
for (NSDictionary *point in startPoints) {
|
|
1971
|
-
if (![point isKindOfClass:[NSDictionary class]]) {
|
|
1972
|
-
continue;
|
|
1973
|
-
}
|
|
1974
|
-
|
|
1975
|
-
CGFloat pointX = [point[@"x"] doubleValue];
|
|
1976
|
-
CGFloat pointY = [point[@"y"] doubleValue];
|
|
1977
|
-
CGFloat xRatio = (pointX - startBounds.origin.x) / startWidth;
|
|
1978
|
-
CGFloat yRatio = (pointY - startBounds.origin.y) / startHeight;
|
|
1979
|
-
CGFloat x = MIN(1.0f, MAX(0.0f, newBounds.origin.x + (xRatio * newWidth)));
|
|
1980
|
-
CGFloat y = MIN(1.0f, MAX(0.0f, newBounds.origin.y + (yRatio * newHeight)));
|
|
1981
|
-
[transformedPoints addObject:@{@"x": @(x), @"y": @(y)}];
|
|
1982
|
-
}
|
|
1983
|
-
|
|
1984
|
-
annotation[@"points"] = transformedPoints;
|
|
1985
|
-
return;
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
|
-
CGFloat x = MIN(1.0f, MAX(0.0f, newBounds.origin.x));
|
|
1989
|
-
CGFloat y = MIN(1.0f, MAX(0.0f, newBounds.origin.y));
|
|
1990
|
-
CGFloat width = MIN(1.0f, MAX(0.01f, newBounds.size.width));
|
|
1991
|
-
CGFloat height = MIN(1.0f, MAX(0.01f, newBounds.size.height));
|
|
1992
|
-
annotation[@"bounds"] = @{@"x": @(x),
|
|
1993
|
-
@"y": @(y),
|
|
1994
|
-
@"width": @(width),
|
|
1995
|
-
@"height": @(height)};
|
|
1996
|
-
}
|
|
1997
|
-
|
|
1998
|
-
- (void)drawSelectionDecoration
|
|
1999
|
-
{
|
|
2000
|
-
if (!_annotationMode || !_annotationEditable || ![_annotationTool isEqualToString:@"select"]) {
|
|
2001
|
-
return;
|
|
2002
|
-
}
|
|
2003
|
-
|
|
2004
|
-
NSDictionary *annotation = [self selectedAnnotation];
|
|
2005
|
-
if (!annotation) {
|
|
2006
|
-
return;
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
NSNumber *pageIndexValue = annotation[@"page"];
|
|
2010
|
-
NSInteger pageIndex = pageIndexValue.integerValue - 1;
|
|
2011
|
-
if (pageIndex < 0 || pageIndex >= _pdfDocument.pageCount) {
|
|
2012
|
-
return;
|
|
2013
|
-
}
|
|
2014
|
-
|
|
2015
|
-
PDFPage *page = [_pdfDocument pageAtIndex:pageIndex];
|
|
2016
|
-
CGRect rect = [self viewRectForAnnotation:annotation page:page];
|
|
2017
|
-
if (CGRectIsEmpty(rect)) {
|
|
2018
|
-
return;
|
|
2019
|
-
}
|
|
2020
|
-
|
|
2021
|
-
UIColor *outlineColor = [UIColor colorWithRed:0.13 green:0.27 blue:0.67 alpha:0.9];
|
|
2022
|
-
UIBezierPath *outlinePath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:4.0f];
|
|
2023
|
-
outlinePath.lineWidth = 2.0f;
|
|
2024
|
-
[outlineColor setStroke];
|
|
2025
|
-
[outlinePath stroke];
|
|
2026
|
-
|
|
2027
|
-
if ([self annotationSupportsResize:annotation]) {
|
|
2028
|
-
CGRect resizeHandle = [self resizeHandleRectForRect:rect];
|
|
2029
|
-
[[UIColor colorWithRed:0.13 green:0.27 blue:0.67 alpha:0.95] setFill];
|
|
2030
|
-
UIBezierPath *resizePath = [UIBezierPath bezierPathWithRoundedRect:resizeHandle cornerRadius:2.0f];
|
|
2031
|
-
[resizePath fill];
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
|
|
2035
|
-
- (NSDictionary *)normalizedBoundsForViewRect:(CGRect)viewRect page:(PDFPage *)page
|
|
2036
|
-
{
|
|
2037
|
-
if (!self.pdfView || !page) {
|
|
2038
|
-
return @{@"x": @0, @"y": @0, @"width": @0, @"height": @0};
|
|
2039
|
-
}
|
|
2040
|
-
|
|
2041
|
-
CGPoint topLeft = [self normalizedPointForViewPoint:viewRect.origin page:page];
|
|
2042
|
-
CGPoint bottomRight = [self normalizedPointForViewPoint:CGPointMake(CGRectGetMaxX(viewRect), CGRectGetMaxY(viewRect)) page:page];
|
|
2043
|
-
|
|
2044
|
-
CGFloat minX = MIN(topLeft.x, bottomRight.x);
|
|
2045
|
-
CGFloat maxX = MAX(topLeft.x, bottomRight.x);
|
|
2046
|
-
CGFloat minY = MIN(topLeft.y, bottomRight.y);
|
|
2047
|
-
CGFloat maxY = MAX(topLeft.y, bottomRight.y);
|
|
2048
|
-
|
|
2049
|
-
return @{@"x": @(MAX(0, minX)),
|
|
2050
|
-
@"y": @(MAX(0, minY)),
|
|
2051
|
-
@"width": @(MAX(0, maxX - minX)),
|
|
2052
|
-
@"height": @(MAX(0, maxY - minY))};
|
|
2053
|
-
}
|
|
2054
|
-
|
|
2055
|
-
- (NSString *)nextLocalAnnotationId
|
|
2056
|
-
{
|
|
2057
|
-
return [NSString stringWithFormat:@"local-%@", RNPDFGenerateAnnotationId()];
|
|
2058
|
-
}
|
|
2059
|
-
|
|
2060
|
-
- (UIColor *)colorForAnnotationType:(NSString *)type style:(NSDictionary *)style
|
|
2061
|
-
{
|
|
2062
|
-
NSString *normalizedType = [self normalizedAnnotationType:type];
|
|
2063
|
-
NSString *colorString = [style isKindOfClass:[NSDictionary class]] ? style[@"color"] : nil;
|
|
2064
|
-
if (colorString) {
|
|
2065
|
-
return RNPDFColorFromHexString(colorString, UIColor.blackColor);
|
|
2066
|
-
}
|
|
2067
|
-
|
|
2068
|
-
if ([normalizedType isEqualToString:@"highlight"]) {
|
|
2069
|
-
return [UIColor colorWithRed:1.0 green:0.93 blue:0.2 alpha:0.35];
|
|
2070
|
-
}
|
|
2071
|
-
if ([normalizedType isEqualToString:@"text"]) {
|
|
2072
|
-
return [UIColor colorWithRed:0.13 green:0.27 blue:0.67 alpha:1.0];
|
|
2073
|
-
}
|
|
2074
|
-
|
|
2075
|
-
return UIColor.blackColor;
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
|
-
- (CGFloat)lineWidthForAnnotation:(NSDictionary *)annotation
|
|
2079
|
-
{
|
|
2080
|
-
NSDictionary *style = [annotation[@"style"] isKindOfClass:[NSDictionary class]] ? annotation[@"style"] : nil;
|
|
2081
|
-
NSNumber *thickness = style[@"thickness"];
|
|
2082
|
-
if ([thickness isKindOfClass:[NSNumber class]]) {
|
|
2083
|
-
return MAX(1.0f, thickness.floatValue);
|
|
2084
|
-
}
|
|
2085
|
-
|
|
2086
|
-
return 2.0f;
|
|
2087
|
-
}
|
|
2088
|
-
|
|
2089
|
-
- (UIFont *)fontForAnnotation:(NSDictionary *)annotation
|
|
2090
|
-
{
|
|
2091
|
-
NSDictionary *style = [annotation[@"style"] isKindOfClass:[NSDictionary class]] ? annotation[@"style"] : nil;
|
|
2092
|
-
NSNumber *fontSize = style[@"fontSize"];
|
|
2093
|
-
CGFloat size = [fontSize isKindOfClass:[NSNumber class]] ? MAX(10.0f, fontSize.floatValue) : 15.0f;
|
|
2094
|
-
return [UIFont systemFontOfSize:size];
|
|
2095
|
-
}
|
|
2096
|
-
|
|
2097
|
-
- (NSTextAlignment)alignmentForAnnotation:(NSDictionary *)annotation
|
|
2098
|
-
{
|
|
2099
|
-
NSDictionary *style = [annotation[@"style"] isKindOfClass:[NSDictionary class]] ? annotation[@"style"] : nil;
|
|
2100
|
-
NSString *alignment = style[@"textAlign"];
|
|
2101
|
-
if ([alignment isEqualToString:@"center"]) {
|
|
2102
|
-
return NSTextAlignmentCenter;
|
|
2103
|
-
}
|
|
2104
|
-
if ([alignment isEqualToString:@"right"]) {
|
|
2105
|
-
return NSTextAlignmentRight;
|
|
2106
|
-
}
|
|
2107
|
-
|
|
2108
|
-
return NSTextAlignmentLeft;
|
|
2109
|
-
}
|
|
2110
|
-
|
|
2111
|
-
- (void)drawRect:(CGRect)rect
|
|
2112
|
-
{
|
|
2113
|
-
[super drawRect:rect];
|
|
2114
|
-
|
|
2115
|
-
if (!_pdfDocument || _draftAnnotations.count == 0) {
|
|
2116
|
-
return;
|
|
2117
|
-
}
|
|
2118
|
-
|
|
2119
|
-
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
2120
|
-
if (!context) {
|
|
2121
|
-
return;
|
|
2122
|
-
}
|
|
2123
|
-
|
|
2124
|
-
for (NSDictionary *annotation in _draftAnnotations) {
|
|
2125
|
-
NSNumber *pageIndexValue = annotation[@"page"];
|
|
2126
|
-
NSInteger pageIndex = pageIndexValue.integerValue - 1;
|
|
2127
|
-
if (pageIndex < 0 || pageIndex >= _pdfDocument.pageCount) {
|
|
2128
|
-
continue;
|
|
2129
|
-
}
|
|
2130
|
-
|
|
2131
|
-
PDFPage *page = [_pdfDocument pageAtIndex:pageIndex];
|
|
2132
|
-
NSString *type = [self normalizedAnnotationType:annotation[@"type"]];
|
|
2133
|
-
if ([type isEqualToString:@"ink"]) {
|
|
2134
|
-
NSArray *points = annotation[@"points"];
|
|
2135
|
-
if (points.count < 2) {
|
|
2136
|
-
continue;
|
|
2137
|
-
}
|
|
2138
|
-
|
|
2139
|
-
UIBezierPath *path = [UIBezierPath bezierPath];
|
|
2140
|
-
BOOL firstPoint = YES;
|
|
2141
|
-
for (NSDictionary *point in points) {
|
|
2142
|
-
CGPoint normalizedPoint = CGPointMake([point[@"x"] doubleValue], [point[@"y"] doubleValue]);
|
|
2143
|
-
CGPoint viewPoint = [self viewPointForNormalizedPoint:normalizedPoint page:page];
|
|
2144
|
-
if (firstPoint) {
|
|
2145
|
-
[path moveToPoint:viewPoint];
|
|
2146
|
-
firstPoint = NO;
|
|
2147
|
-
} else {
|
|
2148
|
-
[path addLineToPoint:viewPoint];
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
|
|
2152
|
-
[[self colorForAnnotationType:type style:annotation[@"style"]] setStroke];
|
|
2153
|
-
path.lineWidth = [self lineWidthForAnnotation:annotation];
|
|
2154
|
-
path.lineJoinStyle = kCGLineJoinRound;
|
|
2155
|
-
path.lineCapStyle = kCGLineCapRound;
|
|
2156
|
-
[path stroke];
|
|
2157
|
-
} else if ([type isEqualToString:@"text"]) {
|
|
2158
|
-
NSDictionary *bounds = annotation[@"bounds"];
|
|
2159
|
-
CGRect viewRect = [self viewRectForNormalizedBounds:bounds page:page];
|
|
2160
|
-
if (CGRectIsEmpty(viewRect)) {
|
|
2161
|
-
continue;
|
|
2162
|
-
}
|
|
2163
|
-
|
|
2164
|
-
UIColor *borderColor = [self colorForAnnotationType:type style:annotation[@"style"]];
|
|
2165
|
-
[[UIColor colorWithWhite:1.0 alpha:0.78] setFill];
|
|
2166
|
-
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:viewRect cornerRadius:4.0f];
|
|
2167
|
-
[path fill];
|
|
2168
|
-
[borderColor setStroke];
|
|
2169
|
-
path.lineWidth = 1.0f;
|
|
2170
|
-
[path stroke];
|
|
2171
|
-
|
|
2172
|
-
NSString *text = annotation[@"text"];
|
|
2173
|
-
if (![text isKindOfClass:[NSString class]]) {
|
|
2174
|
-
text = @"";
|
|
2175
|
-
}
|
|
2176
|
-
|
|
2177
|
-
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
|
|
2178
|
-
paragraphStyle.alignment = [self alignmentForAnnotation:annotation];
|
|
2179
|
-
NSDictionary *attributes = @{
|
|
2180
|
-
NSFontAttributeName: [self fontForAnnotation:annotation],
|
|
2181
|
-
NSForegroundColorAttributeName: borderColor,
|
|
2182
|
-
NSParagraphStyleAttributeName: paragraphStyle,
|
|
2183
|
-
};
|
|
2184
|
-
[text drawInRect:CGRectInset(viewRect, 6.0f, 4.0f) withAttributes:attributes];
|
|
2185
|
-
} else if ([type isEqualToString:@"highlight"]) {
|
|
2186
|
-
NSDictionary *bounds = annotation[@"bounds"];
|
|
2187
|
-
CGRect viewRect = [self viewRectForNormalizedBounds:bounds page:page];
|
|
2188
|
-
if (CGRectIsEmpty(viewRect)) {
|
|
2189
|
-
continue;
|
|
2190
|
-
}
|
|
2191
|
-
|
|
2192
|
-
UIColor *fillColor = [self colorForAnnotationType:type style:annotation[@"style"]];
|
|
2193
|
-
CGContextSetFillColorWithColor(context, fillColor.CGColor);
|
|
2194
|
-
CGContextFillRect(context, viewRect);
|
|
2195
|
-
}
|
|
2196
|
-
}
|
|
2197
|
-
|
|
2198
|
-
[self drawSelectionDecoration];
|
|
2199
|
-
}
|
|
2200
|
-
|
|
2201
|
-
- (void)beginInkAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page
|
|
2202
|
-
{
|
|
2203
|
-
if (!self.annotationEditable || !page) {
|
|
2204
|
-
return;
|
|
2205
|
-
}
|
|
2206
|
-
|
|
2207
|
-
NSMutableDictionary *annotation = [@{
|
|
2208
|
-
@"id": [self nextLocalAnnotationId],
|
|
2209
|
-
@"page": @([_pdfDocument indexForPage:page] + 1),
|
|
2210
|
-
@"type": @"ink",
|
|
2211
|
-
@"points": [NSMutableArray array],
|
|
2212
|
-
@"style": @{@"color": _annotationInkColor ?: @"#111111", @"thickness": @(_annotationInkThickness > 0 ? _annotationInkThickness : 2.0f)}
|
|
2213
|
-
} mutableCopy];
|
|
2214
|
-
|
|
2215
|
-
[_draftAnnotations addObject:annotation];
|
|
2216
|
-
_activeInkAnnotation = annotation;
|
|
2217
|
-
[self appendInkPointAtViewPoint:viewPoint page:page];
|
|
2218
|
-
}
|
|
2219
|
-
|
|
2220
|
-
- (void)appendInkPointAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page
|
|
2221
|
-
{
|
|
2222
|
-
if (!_activeInkAnnotation || !page) {
|
|
2223
|
-
return;
|
|
2224
|
-
}
|
|
2225
|
-
|
|
2226
|
-
CGPoint normalizedPoint = [self normalizedPointForViewPoint:viewPoint page:page];
|
|
2227
|
-
NSMutableArray *points = _activeInkAnnotation[@"points"];
|
|
2228
|
-
if (![points isKindOfClass:[NSMutableArray class]]) {
|
|
2229
|
-
points = [NSMutableArray array];
|
|
2230
|
-
_activeInkAnnotation[@"points"] = points;
|
|
2231
|
-
}
|
|
2232
|
-
|
|
2233
|
-
[points addObject:@{@"x": @(normalizedPoint.x), @"y": @(normalizedPoint.y)}];
|
|
2234
|
-
[self refreshDisplay];
|
|
2235
|
-
}
|
|
2236
|
-
|
|
2237
|
-
- (void)endInk
|
|
2238
|
-
{
|
|
2239
|
-
_activeInkAnnotation = nil;
|
|
2240
|
-
[self refreshDisplay];
|
|
2241
|
-
}
|
|
2242
|
-
|
|
2243
|
-
- (void)beginMarkupAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page type:(NSString *)type
|
|
2244
|
-
{
|
|
2245
|
-
if (!self.annotationEditable || !page) {
|
|
2246
|
-
return;
|
|
2247
|
-
}
|
|
2248
|
-
|
|
2249
|
-
CGPoint normalizedPoint = [self normalizedPointForViewPoint:viewPoint page:page];
|
|
2250
|
-
_activeMarkupStartNormalized = normalizedPoint;
|
|
2251
|
-
|
|
2252
|
-
NSMutableDictionary *annotation = [@{
|
|
2253
|
-
@"id": [self nextLocalAnnotationId],
|
|
2254
|
-
@"page": @([_pdfDocument indexForPage:page] + 1),
|
|
2255
|
-
@"type": @"highlight",
|
|
2256
|
-
@"bounds": @{@"x": @(normalizedPoint.x), @"y": @(normalizedPoint.y), @"width": @0, @"height": @0},
|
|
2257
|
-
@"style": @{}
|
|
2258
|
-
} mutableCopy];
|
|
2259
|
-
|
|
2260
|
-
[_draftAnnotations addObject:annotation];
|
|
2261
|
-
_activeMarkupAnnotation = annotation;
|
|
2262
|
-
[self refreshDisplay];
|
|
2263
|
-
}
|
|
2264
|
-
|
|
2265
|
-
- (void)updateMarkupAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page
|
|
2266
|
-
{
|
|
2267
|
-
if (!_activeMarkupAnnotation || !page) {
|
|
2268
|
-
return;
|
|
2269
|
-
}
|
|
2270
|
-
|
|
2271
|
-
CGPoint currentPoint = [self normalizedPointForViewPoint:viewPoint page:page];
|
|
2272
|
-
CGFloat minX = MIN(_activeMarkupStartNormalized.x, currentPoint.x);
|
|
2273
|
-
CGFloat minY = MIN(_activeMarkupStartNormalized.y, currentPoint.y);
|
|
2274
|
-
CGFloat maxX = MAX(_activeMarkupStartNormalized.x, currentPoint.x);
|
|
2275
|
-
CGFloat maxY = MAX(_activeMarkupStartNormalized.y, currentPoint.y);
|
|
2276
|
-
|
|
2277
|
-
_activeMarkupAnnotation[@"bounds"] = @{@"x": @(minX), @"y": @(minY), @"width": @(MAX(0, maxX - minX)), @"height": @(MAX(0, maxY - minY))};
|
|
2278
|
-
[self refreshDisplay];
|
|
2279
|
-
}
|
|
2280
|
-
|
|
2281
|
-
- (void)endMarkup
|
|
2282
|
-
{
|
|
2283
|
-
_activeMarkupAnnotation = nil;
|
|
2284
|
-
[self refreshDisplay];
|
|
2285
|
-
}
|
|
2286
|
-
|
|
2287
|
-
- (void)createTextAnnotationAtViewPoint:(CGPoint)viewPoint page:(PDFPage *)page
|
|
2288
|
-
{
|
|
2289
|
-
if (!self.annotationEditable || !page) {
|
|
2290
|
-
return;
|
|
2291
|
-
}
|
|
2292
|
-
|
|
2293
|
-
[self commitTextEditingIfNeeded];
|
|
2294
|
-
|
|
2295
|
-
CGPoint normalizedPoint = [self normalizedPointForViewPoint:viewPoint page:page];
|
|
2296
|
-
CGFloat width = 0.25f;
|
|
2297
|
-
CGFloat height = 0.12f;
|
|
2298
|
-
CGFloat maxX = MAX(0.0f, 1.0f - width);
|
|
2299
|
-
CGFloat maxY = MAX(0.0f, 1.0f - height);
|
|
2300
|
-
CGFloat x = MIN(MAX(normalizedPoint.x, 0.0f), maxX);
|
|
2301
|
-
CGFloat y = MIN(MAX(normalizedPoint.y, 0.0f), maxY);
|
|
2302
|
-
NSDictionary *bounds = @{@"x": @(x), @"y": @(y), @"width": @(width), @"height": @(height)};
|
|
2303
|
-
|
|
2304
|
-
NSMutableDictionary *annotation = [@{
|
|
2305
|
-
@"id": [self nextLocalAnnotationId],
|
|
2306
|
-
@"page": @([_pdfDocument indexForPage:page] + 1),
|
|
2307
|
-
@"type": @"text",
|
|
2308
|
-
@"bounds": bounds,
|
|
2309
|
-
@"text": @"",
|
|
2310
|
-
@"style": @{@"color": @"#2244aa", @"fontSize": @(15.0f), @"textAlign": @"left"}
|
|
2311
|
-
} mutableCopy];
|
|
2312
|
-
|
|
2313
|
-
[_draftAnnotations addObject:annotation];
|
|
2314
|
-
_activeTextAnnotation = annotation;
|
|
2315
|
-
|
|
2316
|
-
UITextView *textView = [[UITextView alloc] initWithFrame:[self viewRectForNormalizedBounds:bounds page:page]];
|
|
2317
|
-
textView.delegate = self;
|
|
2318
|
-
textView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.9f];
|
|
2319
|
-
textView.layer.borderColor = [UIColor colorWithRed:0.2 green:0.4 blue:1.0 alpha:0.9].CGColor;
|
|
2320
|
-
textView.layer.borderWidth = 1.0f;
|
|
2321
|
-
textView.layer.cornerRadius = 4.0f;
|
|
2322
|
-
textView.clipsToBounds = YES;
|
|
2323
|
-
textView.textColor = [self colorForAnnotationType:@"text" style:annotation[@"style"]];
|
|
2324
|
-
textView.font = [self fontForAnnotation:annotation];
|
|
2325
|
-
textView.textAlignment = [self alignmentForAnnotation:annotation];
|
|
2326
|
-
textView.scrollEnabled = YES;
|
|
2327
|
-
textView.returnKeyType = UIReturnKeyDefault;
|
|
2328
|
-
|
|
2329
|
-
if (_activeTextView) {
|
|
2330
|
-
[_activeTextView removeFromSuperview];
|
|
2331
|
-
}
|
|
2332
|
-
|
|
2333
|
-
_activeTextView = textView;
|
|
2334
|
-
[self addSubview:_activeTextView];
|
|
2335
|
-
[_activeTextView becomeFirstResponder];
|
|
2336
|
-
[self refreshDisplay];
|
|
2337
|
-
}
|
|
2338
|
-
|
|
2339
|
-
- (void)updateActiveTextEditorFrame
|
|
2340
|
-
{
|
|
2341
|
-
if (!_activeTextView || !_activeTextAnnotation || !self.pdfDocument || !self.pdfView) {
|
|
2342
|
-
return;
|
|
2343
|
-
}
|
|
2344
|
-
|
|
2345
|
-
NSNumber *pageNumber = _activeTextAnnotation[@"page"];
|
|
2346
|
-
NSInteger pageIndex = pageNumber.integerValue - 1;
|
|
2347
|
-
if (pageIndex < 0 || pageIndex >= self.pdfDocument.pageCount) {
|
|
2348
|
-
return;
|
|
2349
|
-
}
|
|
2350
|
-
|
|
2351
|
-
PDFPage *page = [self.pdfDocument pageAtIndex:pageIndex];
|
|
2352
|
-
_activeTextView.frame = [self viewRectForNormalizedBounds:_activeTextAnnotation[@"bounds"] page:page];
|
|
2353
|
-
}
|
|
2354
|
-
|
|
2355
|
-
- (void)commitTextEditingIfNeeded
|
|
2356
|
-
{
|
|
2357
|
-
if (!_activeTextView || !_activeTextAnnotation) {
|
|
2358
|
-
return;
|
|
2359
|
-
}
|
|
2360
|
-
|
|
2361
|
-
_activeTextAnnotation[@"text"] = _activeTextView.text ?: @"";
|
|
2362
|
-
[_activeTextView resignFirstResponder];
|
|
2363
|
-
[_activeTextView removeFromSuperview];
|
|
2364
|
-
_activeTextView = nil;
|
|
2365
|
-
_activeTextAnnotation = nil;
|
|
2366
|
-
[self refreshDisplay];
|
|
2367
|
-
}
|
|
2368
|
-
|
|
2369
|
-
- (void)textViewDidChange:(UITextView *)textView
|
|
2370
|
-
{
|
|
2371
|
-
if (textView == _activeTextView && _activeTextAnnotation) {
|
|
2372
|
-
_activeTextAnnotation[@"text"] = textView.text ?: @"";
|
|
2373
|
-
[self setNeedsDisplay];
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
|
|
2377
|
-
- (void)textViewDidEndEditing:(UITextView *)textView
|
|
2378
|
-
{
|
|
2379
|
-
if (textView == _activeTextView) {
|
|
2380
|
-
[self commitTextEditingIfNeeded];
|
|
2381
|
-
}
|
|
2382
1140
|
}
|
|
2383
1141
|
|
|
2384
1142
|
@end
|