@reekon-tools/react-native-pdf-canvas 0.1.0 → 0.2.0
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/LICENSE +202 -0
- package/NOTICE +57 -0
- package/PdfCanvas.podspec +68 -39
- package/README.md +213 -1316
- package/android/build.gradle +67 -54
- package/android/consumer-rules.pro +7 -0
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasNativeTest.java +254 -0
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/TestPdfs.java +60 -468
- package/android/src/main/cpp/CMakeLists.txt +54 -0
- package/android/src/main/cpp/pdfcanvas-jni.cpp +262 -0
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfCanvasNative.java +167 -0
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfErrorCode.java +14 -4
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfRasterException.java +10 -4
- package/android/src/reactnative/java/tools/reekon/pdfcanvas/rn/PdfCanvasModule.java +160 -376
- package/android/tools/compile-gate.sh +81 -101
- package/dist/controller.d.ts +14 -0
- package/dist/controller.js +4 -3
- package/dist/index.native.d.ts +5 -0
- package/dist/index.native.js +5 -0
- package/dist/index.web.d.ts +10 -0
- package/dist/index.web.js +10 -0
- package/dist/rasterizer/index.native.d.ts +8 -12
- package/dist/rasterizer/index.native.js +15 -21
- package/dist/rasterizer/native-bridge.d.ts +51 -75
- package/dist/rasterizer/native-bridge.js +49 -33
- package/dist/rasterizer/native.d.ts +45 -0
- package/dist/rasterizer/native.js +123 -0
- package/dist/react/usePdfDocument.d.ts +5 -5
- package/dist/react/usePdfLayer.d.ts +10 -1
- package/dist/react/usePdfLayer.js +10 -2
- package/dist/skia/index.native.d.ts +7 -3
- package/dist/skia/index.native.js +7 -3
- package/dist/skia/index.web.d.ts +4 -2
- package/dist/skia/index.web.js +4 -2
- package/dist/testing/scenes.d.ts +3 -3
- package/dist/testing/scenes.js +4 -4
- package/dist/types.d.ts +36 -42
- package/ios/Sources/PdfCanvasBridge/PdfCanvasModule.mm +234 -536
- package/native/.clangd +5 -0
- package/native/CMakeLists.txt +89 -0
- package/native/core/include/pdfcanvas/document.h +90 -0
- package/native/core/include/pdfcanvas/error.h +47 -0
- package/native/core/include/pdfcanvas/jsi.h +18 -0
- package/native/core/include/pdfcanvas/jsi_config.h +30 -0
- package/native/core/include/pdfcanvas/library.h +28 -0
- package/native/core/include/pdfcanvas/pixels.h +92 -0
- package/native/core/include/pdfcanvas/service.h +87 -0
- package/native/core/include/pdfcanvas/slots.h +113 -0
- package/native/core/include/pdfcanvas/types.h +110 -0
- package/native/core/pdfcanvas-core.cmake +22 -0
- package/native/core/src/document.cpp +516 -0
- package/native/core/src/error.cpp +29 -0
- package/native/core/src/jsi.cpp +66 -0
- package/native/core/src/library.cpp +52 -0
- package/native/core/src/pixels.cpp +45 -0
- package/native/core/src/service.cpp +156 -0
- package/native/core/src/slots.cpp +139 -0
- package/native/tests/fixtures.cpp +451 -0
- package/native/tests/fixtures.h +96 -0
- package/native/tests/harness.h +122 -0
- package/native/tests/main.cpp +64 -0
- package/native/tests/pixels_util.h +126 -0
- package/native/tests/test_document.cpp +485 -0
- package/native/tests/test_service.cpp +130 -0
- package/native/tests/test_slots.cpp +250 -0
- package/package.json +38 -8
- package/react-native.config.js +5 -2
- package/scripts/fetch-pdfium.mjs +487 -0
- package/scripts/pdfium-manifest.json +46 -0
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasCancellationTest.java +0 -226
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasConcurrencyTest.java +0 -239
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasDeviceTimingTest.java +0 -251
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasFailureTest.java +0 -221
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasJsiTransportTest.java +0 -783
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasPhaseTimingTest.java +0 -1388
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasPoisonGuardTest.java +0 -98
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasQuirksTest.java +0 -324
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PdfCanvasRasterizerTest.java +0 -775
- package/android/src/androidTest/java/tools/reekon/pdfcanvas/PoisonsTheProcess.java +0 -20
- package/android/src/jsi/cpp/CMakeLists.txt +0 -33
- package/android/src/jsi/cpp/pdfcanvas-jsi.cpp +0 -469
- package/android/src/jsi/java/tools/reekon/pdfcanvas/jsi/PdfCanvasPixelBridge.java +0 -140
- package/android/src/main/java/tools/reekon/pdfcanvas/PageGeometry.java +0 -45
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfCanvasRasterizer.java +0 -564
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfPlatformQuirks.java +0 -277
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfPreflight.java +0 -214
- package/android/src/main/java/tools/reekon/pdfcanvas/PdfRendererPool.java +0 -234
- package/android/src/main/java/tools/reekon/pdfcanvas/RasterCancellation.java +0 -47
- package/android/src/main/java/tools/reekon/pdfcanvas/RasterPixels.java +0 -143
- package/android/src/main/java/tools/reekon/pdfcanvas/RasterRequest.java +0 -95
- package/dist/rasterizer/android.d.ts +0 -121
- package/dist/rasterizer/android.js +0 -126
- package/dist/rasterizer/ios.d.ts +0 -84
- package/dist/rasterizer/ios.js +0 -155
- package/ios/Package.swift +0 -58
- package/ios/Sources/PdfCanvasCore/PdfCanvasCancellation.m +0 -38
- package/ios/Sources/PdfCanvasCore/PdfCanvasDocumentPool.m +0 -389
- package/ios/Sources/PdfCanvasCore/PdfCanvasErrorCode.m +0 -57
- package/ios/Sources/PdfCanvasCore/PdfCanvasPageGeometry.m +0 -44
- package/ios/Sources/PdfCanvasCore/PdfCanvasPageTransform.m +0 -82
- package/ios/Sources/PdfCanvasCore/PdfCanvasPixelSink.m +0 -37
- package/ios/Sources/PdfCanvasCore/PdfCanvasPreflight.m +0 -158
- package/ios/Sources/PdfCanvasCore/PdfCanvasRasterPixels.m +0 -80
- package/ios/Sources/PdfCanvasCore/PdfCanvasRasterRequest.m +0 -65
- package/ios/Sources/PdfCanvasCore/PdfCanvasRasterizer.m +0 -548
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasCancellation.h +0 -48
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasCore.h +0 -26
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasDocumentPool.h +0 -122
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasErrorCode.h +0 -80
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasPageGeometry.h +0 -79
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasPageTransform.h +0 -129
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasPixelSink.h +0 -100
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasPreflight.h +0 -65
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasRasterPixels.h +0 -111
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasRasterRequest.h +0 -85
- package/ios/Sources/PdfCanvasCore/include/PdfCanvasRasterizer.h +0 -163
- package/ios/Sources/PdfCanvasSlots/PdfCanvasSlots.mm +0 -297
- package/ios/Sources/PdfCanvasSlots/include/PdfCanvasSlots.h +0 -140
- package/ios/Tests/PdfCanvasCoreTests/ConcurrencyTests.swift +0 -358
- package/ios/Tests/PdfCanvasCoreTests/FailureTests.swift +0 -262
- package/ios/Tests/PdfCanvasCoreTests/GeometryTests.swift +0 -173
- package/ios/Tests/PdfCanvasCoreTests/PreviewTests.swift +0 -114
- package/ios/Tests/PdfCanvasCoreTests/RasterAssertions.swift +0 -158
- package/ios/Tests/PdfCanvasCoreTests/RasterizerTests.swift +0 -544
- package/ios/Tests/PdfCanvasCoreTests/SinkTests.swift +0 -287
- package/ios/Tests/PdfCanvasCoreTests/SlotsTests.swift +0 -396
- package/ios/Tests/PdfCanvasCoreTests/TestPdfs.swift +0 -639
- package/ios/Tests/PdfCanvasCoreTests/TimingTests.swift +0 -179
- package/ios/Tests/PdfCanvasCoreTests/TransformTests.swift +0 -283
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
#import <CoreGraphics/CoreGraphics.h>
|
|
2
|
-
#import <Foundation/Foundation.h>
|
|
3
|
-
#import <PDFKit/PDFKit.h>
|
|
4
|
-
|
|
5
|
-
#import "PdfCanvasErrorCode.h"
|
|
6
|
-
|
|
7
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
-
|
|
9
|
-
/** Ceiling on pooled documents. Mirrored by `MAX_POOL_SIZE` in `src/rasterizer/ios.ts`. */
|
|
10
|
-
FOUNDATION_EXPORT const NSInteger kPdfCanvasMaxPoolSize;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* One lane's worth of parsed document: a `CGPDFDocumentRef` and, once something
|
|
14
|
-
* asks for annotations, a `PDFDocument`.
|
|
15
|
-
*
|
|
16
|
-
* THE PDFKit HALF IS LAZY, and that is the whole reason the two live in one
|
|
17
|
-
* object. Every tile the controller asks for passes `annotations: NO` and goes
|
|
18
|
-
* through CGPDF, so a `PDFDocument` opened eagerly at `open()` would parse a
|
|
19
|
-
* second copy of an ARCH-E sheet that the common path never touches. It is opened
|
|
20
|
-
* on the first `annotations: YES` render in this lane and kept, because a thumbnail
|
|
21
|
-
* strip asks repeatedly.
|
|
22
|
-
*
|
|
23
|
-
* ONE LANE, ONE PARSE OF EACH. Neither `CGPDFDocumentRef` nor `PDFDocument` is
|
|
24
|
-
* documented thread-safe, and sharing one across lanes would mean a lock this
|
|
25
|
-
* library owns — which buys nothing over just leasing. Opening the file once per
|
|
26
|
-
* lane is the same argument `PdfRendererPool` makes for opening afresh rather than
|
|
27
|
-
* `dup(2)`-ing a descriptor: independent state is the invariant the code needs,
|
|
28
|
-
* and one extra parse is what it costs.
|
|
29
|
-
*/
|
|
30
|
-
@interface PdfCanvasDocumentLease : NSObject
|
|
31
|
-
|
|
32
|
-
/** Never NULL for a live lease. Owned by this object and released on dealloc. */
|
|
33
|
-
@property(nonatomic, readonly) CGPDFDocumentRef cgDocument;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* The PDFKit document for this lane, opening it if this is the first ask.
|
|
37
|
-
*
|
|
38
|
-
* Fails with `corrupt` if PDFKit refuses a document CoreGraphics accepted, and
|
|
39
|
-
* with `password-required` / `password-incorrect` if it cannot be unlocked — the
|
|
40
|
-
* two engines keep separate locks, so the password has to be presented twice.
|
|
41
|
-
*/
|
|
42
|
-
- (nullable PDFDocument *)pdfKitDocumentWithError:
|
|
43
|
-
(NSError *_Nullable *_Nullable)error;
|
|
44
|
-
|
|
45
|
-
- (instancetype)init NS_UNAVAILABLE;
|
|
46
|
-
|
|
47
|
-
@end
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* A fixed set of parsed documents over the same bytes, leased one at a time.
|
|
51
|
-
*
|
|
52
|
-
* ------------------------------------------------------------------------
|
|
53
|
-
* CLOSE-WHILE-LEASED IS SAFE HERE, AND ON ANDROID IT IS NOT.
|
|
54
|
-
* ------------------------------------------------------------------------
|
|
55
|
-
*
|
|
56
|
-
* `PdfRendererPool.close()` closes every renderer including the ones currently
|
|
57
|
-
* leased, and its own comment calls that "the only honest option": `close()` comes
|
|
58
|
-
* from JS when a document unmounts, and blocking until an in-flight ARCH-D render
|
|
59
|
-
* finishes is worse. It leaves a window.
|
|
60
|
-
*
|
|
61
|
-
* There is no window here, because CoreFoundation refcounts. A lease OWNS its
|
|
62
|
-
* `CGPDFDocumentRef` and releases it in `dealloc`, so `close` dropping the pool's
|
|
63
|
-
* references cannot free a document a render worker is still drawing from — the
|
|
64
|
-
* worker holds the lease, and the last reference goes away when it returns the
|
|
65
|
-
* lease to a closed pool. `close` is therefore non-blocking AND has no
|
|
66
|
-
* use-after-free, which is strictly better than the Android behaviour rather than
|
|
67
|
-
* a different trade.
|
|
68
|
-
*/
|
|
69
|
-
@interface PdfCanvasDocumentPool : NSObject
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @param password nil unless the document needs one. Both engines are unlocked
|
|
73
|
-
* with it — CGPDF eagerly, PDFKit on first use — and a wrong one is
|
|
74
|
-
* `password-incorrect` rather than `corrupt`.
|
|
75
|
-
* @param size clamped to [1, `kPdfCanvasMaxPoolSize`].
|
|
76
|
-
*/
|
|
77
|
-
+ (nullable instancetype)openFileURL:(NSURL *)url
|
|
78
|
-
password:(nullable NSString *)password
|
|
79
|
-
size:(NSInteger)size
|
|
80
|
-
error:(NSError *_Nullable *_Nullable)error
|
|
81
|
-
NS_SWIFT_NAME(open(fileURL:password:size:));
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Opens from bytes with no spool file.
|
|
85
|
-
*
|
|
86
|
-
* Worth contrasting with Android, where `PdfCanvasRasterizer.openBytes` MUST
|
|
87
|
-
* write a temp file first because `PdfRenderer` needs a seekable descriptor and
|
|
88
|
-
* reads through a seek-and-read callback. `CGPDFDocumentCreateWithProvider` over a
|
|
89
|
-
* `CFData` needs no file at all, and every lane can share the same immutable
|
|
90
|
-
* `NSData` because each gets its own provider and its own parse.
|
|
91
|
-
*/
|
|
92
|
-
+ (nullable instancetype)openData:(NSData *)data
|
|
93
|
-
password:(nullable NSString *)password
|
|
94
|
-
size:(NSInteger)size
|
|
95
|
-
error:(NSError *_Nullable *_Nullable)error
|
|
96
|
-
NS_SWIFT_NAME(open(data:password:size:));
|
|
97
|
-
|
|
98
|
-
@property(nonatomic, readonly) NSInteger pageCount;
|
|
99
|
-
/** How many renders can genuinely be in flight at once. */
|
|
100
|
-
@property(nonatomic, readonly) NSInteger size;
|
|
101
|
-
@property(nonatomic, readonly, getter=isClosed) BOOL closed;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Blocks until a lane is free.
|
|
105
|
-
*
|
|
106
|
-
* The wait is where a cancel most often lands — a superseded detail raster
|
|
107
|
-
* typically queues behind a base raster — so the caller re-checks its signal on
|
|
108
|
-
* the far side of this call.
|
|
109
|
-
*/
|
|
110
|
-
- (nullable PdfCanvasDocumentLease *)leaseWithError:
|
|
111
|
-
(NSError *_Nullable *_Nullable)error;
|
|
112
|
-
|
|
113
|
-
/** Always call from a `@finally`-shaped path: a leaked lease starves every later render. */
|
|
114
|
-
- (void)returnLease:(nullable PdfCanvasDocumentLease *)lease;
|
|
115
|
-
|
|
116
|
-
- (void)close;
|
|
117
|
-
|
|
118
|
-
- (instancetype)init NS_UNAVAILABLE;
|
|
119
|
-
|
|
120
|
-
@end
|
|
121
|
-
|
|
122
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
#import <Foundation/Foundation.h>
|
|
2
|
-
|
|
3
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* The eight failure kinds, mirroring `PdfErrorCode` in `src/types.ts` and
|
|
7
|
-
* `PdfErrorCode.java` on Android.
|
|
8
|
-
*
|
|
9
|
-
* The WIRE STRINGS are the TypeScript union members verbatim. They are the
|
|
10
|
-
* contract across the bridge: the binding rejects a promise with
|
|
11
|
-
* `PdfCanvasErrorCodeWire()` and the TS side reconstructs a `PdfError` from it
|
|
12
|
-
* with no translation table in between (`toPdfError` in
|
|
13
|
-
* `src/rasterizer/native-bridge.ts`). Adding a member here without adding it
|
|
14
|
-
* there produces a `PdfError` with a code no consumer can switch on, so the
|
|
15
|
-
* lists have to move together — and there are now THREE of them, since Android
|
|
16
|
-
* has its own copy.
|
|
17
|
-
*/
|
|
18
|
-
typedef NS_ENUM(NSInteger, PdfCanvasErrorCode) {
|
|
19
|
-
PdfCanvasErrorCodeNotFound = 0,
|
|
20
|
-
PdfCanvasErrorCodePasswordRequired,
|
|
21
|
-
PdfCanvasErrorCodePasswordIncorrect,
|
|
22
|
-
PdfCanvasErrorCodeCorrupt,
|
|
23
|
-
PdfCanvasErrorCodeUnsupported,
|
|
24
|
-
PdfCanvasErrorCodeCancelled,
|
|
25
|
-
PdfCanvasErrorCodeOutOfMemory,
|
|
26
|
-
PdfCanvasErrorCodeBackendFailure,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* The `NSError` domain every failure in this library carries.
|
|
31
|
-
*
|
|
32
|
-
* `NSError` rather than an exception subclass, and that is not merely idiomatic:
|
|
33
|
-
* Objective-C exceptions are not a control-flow mechanism ARC unwinds safely, and
|
|
34
|
-
* this library allocates CoreGraphics objects on every path. Android can afford a
|
|
35
|
-
* checked `PdfRasterException` because the JVM unwinds; here the `NSError **`
|
|
36
|
-
* out-parameter is what keeps every `CGPDFDocumentRelease` reachable.
|
|
37
|
-
*/
|
|
38
|
-
FOUNDATION_EXPORT NSErrorDomain const PdfCanvasErrorDomain;
|
|
39
|
-
|
|
40
|
-
/** The TypeScript union member for a code. Never nil. */
|
|
41
|
-
FOUNDATION_EXPORT NSString *PdfCanvasErrorCodeWire(PdfCanvasErrorCode code);
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Builds an error in `PdfCanvasErrorDomain` whose `code` is the enum and whose
|
|
45
|
-
* `localizedDescription` is `message`.
|
|
46
|
-
*
|
|
47
|
-
* The `underlying` error is always kept when there is one. A `corrupt` verdict
|
|
48
|
-
* that turns out to be a truncated download is only diagnosable from whatever
|
|
49
|
-
* CoreGraphics or the file system said first.
|
|
50
|
-
*/
|
|
51
|
-
FOUNDATION_EXPORT NSError *PdfCanvasMakeError(
|
|
52
|
-
PdfCanvasErrorCode code,
|
|
53
|
-
NSString *message,
|
|
54
|
-
NSError *_Nullable underlying);
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Reads a code back out of an error.
|
|
58
|
-
*
|
|
59
|
-
* Anything not in `PdfCanvasErrorDomain` — an `NSError` from `NSFileManager`, say
|
|
60
|
-
* — reads as `PdfCanvasErrorCodeBackendFailure`, because a foreign error reaching
|
|
61
|
-
* a caller that wanted a code is a mapping this library forgot rather than a new
|
|
62
|
-
* kind of failure.
|
|
63
|
-
*/
|
|
64
|
-
FOUNDATION_EXPORT PdfCanvasErrorCode PdfCanvasErrorCodeOf(NSError *error);
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Assigns to an `NSError **` out-parameter if the caller supplied one, and
|
|
68
|
-
* returns nil so a failing method can `return PdfCanvasFail(error, ...)`.
|
|
69
|
-
*
|
|
70
|
-
* Exists because the alternative — `if (error) *error = ...; return nil;` — is
|
|
71
|
-
* three lines that get shortened to two on a bad day, and the line that gets
|
|
72
|
-
* dropped is the assignment.
|
|
73
|
-
*/
|
|
74
|
-
FOUNDATION_EXPORT id _Nullable PdfCanvasFail(
|
|
75
|
-
NSError *_Nullable *_Nullable out,
|
|
76
|
-
PdfCanvasErrorCode code,
|
|
77
|
-
NSString *message,
|
|
78
|
-
NSError *_Nullable underlying);
|
|
79
|
-
|
|
80
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
#import <CoreGraphics/CoreGraphics.h>
|
|
2
|
-
#import <Foundation/Foundation.h>
|
|
3
|
-
|
|
4
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A page's intrinsic size in PDF points, mirroring `PageGeometry` in
|
|
8
|
-
* `src/types.ts`.
|
|
9
|
-
*
|
|
10
|
-
* POST-ROTATION, per that contract: a 612x792 page carrying `/Rotate 90` reports
|
|
11
|
-
* 792x612. Unlike Android — where `PdfRenderer.Page.getWidth()` happens to
|
|
12
|
-
* already be post-rotation and there is no way to read `/Rotate` at all below
|
|
13
|
-
* API 35 — this backend computes it, because CoreGraphics reports the raw box and
|
|
14
|
-
* the raw `/Rotate` separately and applies neither.
|
|
15
|
-
*
|
|
16
|
-
* MEASURED, both halves: `CGPDFPageGetBoxRect(page, kCGPDFCropBox)` on a
|
|
17
|
-
* `/Rotate 90` letter page returns `(0, 0, 612, 792)` — unrotated — and
|
|
18
|
-
* `CGPDFPageGetRotationAngle` returns 90. So the swap below is this library's
|
|
19
|
-
* arithmetic and is pinned by `pageGeometryIsPostRotation` in the Swift suite.
|
|
20
|
-
*
|
|
21
|
-
* `rotationDegrees` reports the page's REAL `/Rotate`, which is what the web
|
|
22
|
-
* PDFium backend does and the opposite of what Android does (it reports 0,
|
|
23
|
-
* because it cannot read the value). `PageGeometry.rotation` is informational to
|
|
24
|
-
* this package — nothing applies a further rotation on the strength of it — and
|
|
25
|
-
* `src/rasterizer/native-bridge.ts` documents the divergence at the field.
|
|
26
|
-
*
|
|
27
|
-
* `cropBox` is the box the raster is defined against: `kCGPDFCropBox`
|
|
28
|
-
* INTERSECTED with `kCGPDFMediaBox`, in PDF user space (y-up), origin NOT
|
|
29
|
-
* normalised away. It is exposed rather than kept private because it is the only
|
|
30
|
-
* input `PdfCanvasPdfToDocTransform` needs, and that is what makes the transform
|
|
31
|
-
* testable without a document.
|
|
32
|
-
*/
|
|
33
|
-
@interface PdfCanvasPageGeometry : NSObject
|
|
34
|
-
|
|
35
|
-
@property(nonatomic, readonly) NSInteger index;
|
|
36
|
-
/** Width in PDF points, after `/Rotate`. */
|
|
37
|
-
@property(nonatomic, readonly) CGFloat widthPoints;
|
|
38
|
-
/** Height in PDF points, after `/Rotate`. */
|
|
39
|
-
@property(nonatomic, readonly) CGFloat heightPoints;
|
|
40
|
-
/** The page's `/Rotate`, normalised to 0, 90, 180 or 270. */
|
|
41
|
-
@property(nonatomic, readonly) NSInteger rotationDegrees;
|
|
42
|
-
/** CropBox ∩ MediaBox, in PDF user space. NOT rotated, NOT origin-normalised. */
|
|
43
|
-
@property(nonatomic, readonly) CGRect cropBox;
|
|
44
|
-
|
|
45
|
-
- (instancetype)initWithIndex:(NSInteger)index
|
|
46
|
-
cropBox:(CGRect)cropBox
|
|
47
|
-
rotationDegrees:(NSInteger)rotationDegrees NS_DESIGNATED_INITIALIZER;
|
|
48
|
-
- (instancetype)init NS_UNAVAILABLE;
|
|
49
|
-
|
|
50
|
-
@end
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Normalises any `/Rotate` value to 0, 90, 180 or 270.
|
|
54
|
-
*
|
|
55
|
-
* The spec allows only multiples of 90 and real files carry negatives (`-90`) and
|
|
56
|
-
* out-of-range values (`450`). A value that is not a multiple of 90 after
|
|
57
|
-
* normalisation is reported as 0 rather than rounded: rounding 45 to either
|
|
58
|
-
* neighbour is a guess, and drawing the page unrotated is the one answer that is
|
|
59
|
-
* merely wrong rather than wrong AND surprising.
|
|
60
|
-
*/
|
|
61
|
-
FOUNDATION_EXPORT NSInteger PdfCanvasNormalizeRotation(NSInteger degrees);
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* CropBox ∩ MediaBox for a page, in PDF user space.
|
|
65
|
-
*
|
|
66
|
-
* `CGPDFPageGetBoxRect(page, kCGPDFCropBox)` already falls back to the media box
|
|
67
|
-
* when there is no crop box, so the common case is a no-op — but it does NOT do
|
|
68
|
-
* the intersection the PDF spec requires ("the crop box shall be intersected with
|
|
69
|
-
* the media box"), and a file whose crop box overhangs its media box would
|
|
70
|
-
* otherwise produce a page larger than the paper, with every rect the layout
|
|
71
|
-
* function derives from it wrong by the overhang.
|
|
72
|
-
*
|
|
73
|
-
* A degenerate intersection falls back to the MEDIA box rather than to an empty
|
|
74
|
-
* rect. A zero-area page would make `fitScale` non-finite and the planner would
|
|
75
|
-
* emit nothing at all, which presents as a blank document with no error anywhere.
|
|
76
|
-
*/
|
|
77
|
-
FOUNDATION_EXPORT CGRect PdfCanvasEffectiveCropBox(CGPDFPageRef page);
|
|
78
|
-
|
|
79
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
#import <CoreGraphics/CoreGraphics.h>
|
|
2
|
-
#import <Foundation/Foundation.h>
|
|
3
|
-
|
|
4
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* The three affine transforms this backend is built out of.
|
|
8
|
-
*
|
|
9
|
-
* THEIR OWN FILE, WITH NO DOCUMENT IN SIGHT, because they are the part that can
|
|
10
|
-
* be wrong in a way that looks plausible. A rotation applied the wrong way round,
|
|
11
|
-
* a crop-box origin left in, a y-flip that lands half a pixel off — none of those
|
|
12
|
-
* throws, and all of them are checkable by mapping four corners with no PDF, no
|
|
13
|
-
* bitmap and no CoreGraphics state. `PdfCanvasTransformTests.swift` does exactly
|
|
14
|
-
* that, and only then does `PdfCanvasRasterizerTests.swift` check that a rendered
|
|
15
|
-
* page agrees.
|
|
16
|
-
*
|
|
17
|
-
* ------------------------------------------------------------------------
|
|
18
|
-
* THE THREE SPACES
|
|
19
|
-
* ------------------------------------------------------------------------
|
|
20
|
-
*
|
|
21
|
-
* PDF USER SPACE — y-UP, origin wherever the page's boxes say. This is the space
|
|
22
|
-
* `CGContextDrawPDFPage` draws in, and it applies neither the crop box's origin
|
|
23
|
-
* nor `/Rotate` (both MEASURED — see the notes on each function below).
|
|
24
|
-
*
|
|
25
|
-
* DOC SPACE — y-DOWN, origin at the ROTATED page's top-left, units of PDF points.
|
|
26
|
-
* This is the package's one coordinate system (`src/types.ts`: "PDF points,
|
|
27
|
-
* y-down, origin at the page's top-left, exactly what PDFium's
|
|
28
|
-
* CPDF_Page::GetDisplayMatrix() emits"). Every rect that crosses the JS boundary
|
|
29
|
-
* is in it.
|
|
30
|
-
*
|
|
31
|
-
* RASTER SPACE — the `CGBitmapContext`'s own: y-UP from the bottom-left, units of
|
|
32
|
-
* device pixels, extent exactly the request's `pixelWidth` x `pixelHeight`.
|
|
33
|
-
*
|
|
34
|
-
* ------------------------------------------------------------------------
|
|
35
|
-
* WHY THE PIXEL HEIGHT IN THE FLIP IS THE ROUNDED ONE, AND WHY THAT IS EXACT
|
|
36
|
-
* ------------------------------------------------------------------------
|
|
37
|
-
*
|
|
38
|
-
* `PdfCanvasDocToRasterTransform` flips through `pixelHeight`, which is
|
|
39
|
-
* `round(docHeight * scale)` and therefore up to half a pixel away from
|
|
40
|
-
* `docHeight * scale`. That looks like it would make two rasters requested at the
|
|
41
|
-
* same scale disagree where they overlap — the property the cache and the
|
|
42
|
-
* overlapping detail pieces depend on, and the one `tileMatrix` on Android has a
|
|
43
|
-
* long comment about.
|
|
44
|
-
*
|
|
45
|
-
* It does not, and the cancellation is exact. A doc point `dy` lands at raster
|
|
46
|
-
* y = `H - (dy - docY) * scale`, and a reader indexing rows from the TOP sees
|
|
47
|
-
* `H - y` = `(dy - docY) * scale`. `H` cancels. So the rounding decides only how
|
|
48
|
-
* much of the far edge exists at all — at most half a pixel, left showing the
|
|
49
|
-
* background fill, exactly as on Android — and never where content lands relative
|
|
50
|
-
* to the raster's origin. `tileTransformsAgreeWhereTheyOverlap` pins it with two
|
|
51
|
-
* rects whose pixel heights round in opposite directions.
|
|
52
|
-
*
|
|
53
|
-
* `scale` is likewise used EXACTLY as requested and never re-derived from
|
|
54
|
-
* `pixelWidth / docWidth`, for the reason `PdfCanvasRasterizer.java` gives: it is
|
|
55
|
-
* what makes two rasters at the same scale agree pixel-for-pixel over their
|
|
56
|
-
* overlap. Re-deriving would instead make each raster cover its doc rect to the
|
|
57
|
-
* last sub-pixel, at the cost of every pair of neighbours being drawn at
|
|
58
|
-
* imperceptibly different scales.
|
|
59
|
-
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* PDF user space -> doc space.
|
|
63
|
-
*
|
|
64
|
-
* `cropBox` is CropBox ∩ MediaBox in PDF user space, origin NOT normalised away;
|
|
65
|
-
* `rotationDegrees` is the page's `/Rotate`, already normalised to 0/90/180/270.
|
|
66
|
-
*
|
|
67
|
-
* MEASURED, and this function exists because both halves came out "no":
|
|
68
|
-
* `CGContextDrawPDFPage` applies NEITHER the crop box origin NOR `/Rotate`. On a
|
|
69
|
-
* `/Rotate 90` letter page, drawing with the rotation in this transform puts the
|
|
70
|
-
* marker at the displayed top-right (correct) and drawing without it puts it at
|
|
71
|
-
* the top-left, clipped (wrong). On a page with MediaBox `0 0 400 400` and CropBox
|
|
72
|
-
* `100 150 300 350`, the `-cropBox.minX` term is what puts the crop box's own
|
|
73
|
-
* top-left corner at doc (0, 0).
|
|
74
|
-
*
|
|
75
|
-
* Every one of the four cases has determinant -1, and that is not a bug: doc space
|
|
76
|
-
* is y-down while PDF space is y-up, so a rotation in the DISPLAY sense is a
|
|
77
|
-
* rotation composed with a reflection in raw coordinates. A case that came out
|
|
78
|
-
* +1 would be the one to distrust.
|
|
79
|
-
*/
|
|
80
|
-
FOUNDATION_EXPORT CGAffineTransform PdfCanvasPdfToDocTransform(
|
|
81
|
-
CGRect cropBox, NSInteger rotationDegrees);
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Doc space -> raster space, for one request.
|
|
85
|
-
*
|
|
86
|
-
* `pixelHeight` is the destination bitmap's height in device pixels — the
|
|
87
|
-
* request's own `pixelHeight`, not `docHeight * scale`. See the file note for why
|
|
88
|
-
* that is exact rather than approximate.
|
|
89
|
-
*/
|
|
90
|
-
FOUNDATION_EXPORT CGAffineTransform PdfCanvasDocToRasterTransform(
|
|
91
|
-
double docX, double docY, double scale, NSInteger pixelHeight);
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Doc space -> the y-up, page-sized space PDFKit draws into.
|
|
95
|
-
*
|
|
96
|
-
* `pageHeightPoints` is the POST-ROTATION crop-box height, i.e.
|
|
97
|
-
* `PdfCanvasPageGeometry.heightPoints`.
|
|
98
|
-
*
|
|
99
|
-
* ------------------------------------------------------------------------
|
|
100
|
-
* PDFKit'S ASYMMETRY, MEASURED, AND IT IS A TRAP
|
|
101
|
-
* ------------------------------------------------------------------------
|
|
102
|
-
*
|
|
103
|
-
* `-[PDFPage drawWithBox:toContext:]` DOES apply `/Rotate` and DOES normalise the
|
|
104
|
-
* box origin — so, unlike the CGPDF path, nothing here may rotate anything.
|
|
105
|
-
* But `-[PDFPage boundsForBox:]` does NOT apply `/Rotate`: on the same
|
|
106
|
-
* `/Rotate 90` letter page it returns `(0, 0, 612, 792)` while `drawWithBox:`
|
|
107
|
-
* draws a 792 x 612 landscape page. It DOES report the crop box's origin
|
|
108
|
-
* (`(100, 150, 200, 200)` for the offset-crop fixture), so it is not simply
|
|
109
|
-
* normalising either.
|
|
110
|
-
*
|
|
111
|
-
* The consequence, and the whole reason this takes the height as an argument
|
|
112
|
-
* rather than reading it off the page: flipping by `boundsForBox:.size.height`
|
|
113
|
-
* flips a rotated page by the WRONG number, and the result is a page drawn
|
|
114
|
-
* rotated, off-centre and clipped, with no error anywhere. The height must come
|
|
115
|
-
* from `PdfCanvasPageGeometry`, which computes the post-rotation size from the
|
|
116
|
-
* CGPDF crop box and rotation. Widely-copied sample code — flip by
|
|
117
|
-
* `page.bounds(for:).size.height`, then draw — is correct only for unrotated
|
|
118
|
-
* pages.
|
|
119
|
-
*
|
|
120
|
-
* With the height right, the two engines agree byte-for-byte on a page with no
|
|
121
|
-
* annotations: 0 of 1,280,000 bytes differing, maxDelta 0, at scale 4 over an
|
|
122
|
-
* 800x400 raster. That equality is what lets `annotations` pick an engine per
|
|
123
|
-
* render without the geometry moving, and it is asserted by
|
|
124
|
-
* `bothEnginesAgreeOnAPageWithNoAnnotations`.
|
|
125
|
-
*/
|
|
126
|
-
FOUNDATION_EXPORT CGAffineTransform PdfCanvasDocToPdfKitTransform(
|
|
127
|
-
double pageHeightPoints);
|
|
128
|
-
|
|
129
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
#import <Foundation/Foundation.h>
|
|
2
|
-
|
|
3
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Where a raster's bytes are to be written.
|
|
7
|
-
*
|
|
8
|
-
* ------------------------------------------------------------------------
|
|
9
|
-
* THIS PROTOCOL IS WHY THE iOS TRANSPORT COSTS ZERO COPIES.
|
|
10
|
-
* ------------------------------------------------------------------------
|
|
11
|
-
*
|
|
12
|
-
* Android's fast path costs ONE full-raster copy and cannot do better: a
|
|
13
|
-
* `Bitmap` owns its own pixel memory, `PdfRenderer.render` writes into that, and
|
|
14
|
-
* the best `nativeStoreFromBitmap` can do is one `memcpy` out of it. There is no
|
|
15
|
-
* way to tell `PdfRenderer` where to put the pixels.
|
|
16
|
-
*
|
|
17
|
-
* `CGBitmapContextCreate` takes the destination pointer as an argument. So the
|
|
18
|
-
* bytes are written ONCE, by CoreGraphics, straight into the buffer the JS
|
|
19
|
-
* `ArrayBuffer` will later wrap. There is no bitmap object, no `NSData`, no
|
|
20
|
-
* `memcpy`, and nothing for a garbage collector to notice.
|
|
21
|
-
*
|
|
22
|
-
* The core does not know what a slot is, and must not: `PdfCanvasCore` builds and
|
|
23
|
-
* is tested with no React Native and no JSI anywhere near it. So the destination
|
|
24
|
-
* is injected, this protocol is the seam, and
|
|
25
|
-
* `ios/Sources/PdfCanvasBridge/PdfCanvasSlots.mm` is its only production
|
|
26
|
-
* implementation. `PdfCanvasHeapSink` below is the default and is what every
|
|
27
|
-
* pixel-reading caller — the whole Swift suite, and the base64 fallback — uses.
|
|
28
|
-
*
|
|
29
|
-
* ------------------------------------------------------------------------
|
|
30
|
-
* THE ORDER IS RESERVE, FILL, PUBLISH, AND IT IS LOAD-BEARING.
|
|
31
|
-
* ------------------------------------------------------------------------
|
|
32
|
-
*
|
|
33
|
-
* The Android JSI file records the bug this shape avoids, in its own words: a
|
|
34
|
-
* buffer that is reachable from a process-wide map BEFORE it is filled can be
|
|
35
|
-
* freed by a teardown running on another thread while a render worker is still
|
|
36
|
-
* writing into it — "silent heap corruption, weeks from the change that caused
|
|
37
|
-
* it". So a reserved buffer is owned by the sink object alone, held on the
|
|
38
|
-
* rendering thread's stack, and becomes reachable only at `publish`.
|
|
39
|
-
*
|
|
40
|
-
* A REFUSAL COSTS NOTHING, because it happens before the draw. `reserveBytes:`
|
|
41
|
-
* returning NULL means "no fast destination available"; the rasterizer falls
|
|
42
|
-
* straight through to a heap sink and the tile still goes out. Contrast Android,
|
|
43
|
-
* where the refusal can only be discovered after the raster exists.
|
|
44
|
-
*/
|
|
45
|
-
@protocol PdfCanvasPixelSink <NSObject>
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Reserve `length` bytes, zeroed, and return a pointer to them — or NULL to
|
|
49
|
-
* refuse.
|
|
50
|
-
*
|
|
51
|
-
* Called AT MOST ONCE per sink, before anything is drawn. The returned memory
|
|
52
|
-
* must stay valid and stable until `pdfCanvasPublish` or `pdfCanvasAbandon`, and
|
|
53
|
-
* after a publish it must stay valid until whoever took it is done with it.
|
|
54
|
-
*
|
|
55
|
-
* ZEROED IS PART OF THE CONTRACT, not an accident of the implementation. It is
|
|
56
|
-
* what makes `PdfCanvasBackgroundTransparent` free, and it is the invariant that
|
|
57
|
-
* stops a published buffer ever handing out memory nobody wrote — the failure
|
|
58
|
-
* mode there being a tile of somebody else's heap.
|
|
59
|
-
*/
|
|
60
|
-
- (nullable void *)pdfCanvasReserveBytes:(NSUInteger)length;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Publish the reserved buffer and return the identifier a caller can redeem it
|
|
64
|
-
* with, or 0 if this sink has no identifier (the heap sink).
|
|
65
|
-
*
|
|
66
|
-
* MUST NOT FAIL. Every reason a publish could be refused — no memory, an
|
|
67
|
-
* identifier already in use — is decided at `reserveBytes:`, before the raster
|
|
68
|
-
* exists. That is deliberate: Android's equivalent can refuse after the copy, and
|
|
69
|
-
* the only thing a caller can do at that point is throw a finished raster away.
|
|
70
|
-
*/
|
|
71
|
-
- (int64_t)pdfCanvasPublish;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Drop the buffer, published or not. Idempotent.
|
|
75
|
-
*
|
|
76
|
-
* Called on every path that ABANDONS a raster after reserving for it — a
|
|
77
|
-
* cancellation observed after the draw finished, a failure between the draw and
|
|
78
|
-
* the result being built. Without it each one strands a whole raster of native
|
|
79
|
-
* memory that nothing will ever come looking for.
|
|
80
|
-
*/
|
|
81
|
-
- (void)pdfCanvasAbandon;
|
|
82
|
-
|
|
83
|
-
@end
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* The default destination: an `NSMutableData`.
|
|
87
|
-
*
|
|
88
|
-
* `-[NSMutableData dataWithLength:]` is documented to zero its bytes, which is
|
|
89
|
-
* the `pdfCanvasReserveBytes:` contract met for free. `pdfCanvasPublish` returns
|
|
90
|
-
* 0 and `data` is how the bytes are read back — which is what the base64
|
|
91
|
-
* transport, every pixel-reading test, and `PdfCanvasRasterPixels.bytes` use.
|
|
92
|
-
*/
|
|
93
|
-
@interface PdfCanvasHeapSink : NSObject <PdfCanvasPixelSink>
|
|
94
|
-
|
|
95
|
-
/** The reserved buffer, or nil before `pdfCanvasReserveBytes:` / after abandon. */
|
|
96
|
-
@property(nonatomic, readonly, nullable) NSMutableData *data;
|
|
97
|
-
|
|
98
|
-
@end
|
|
99
|
-
|
|
100
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
#import <Foundation/Foundation.h>
|
|
2
|
-
|
|
3
|
-
#import "PdfCanvasErrorCode.h"
|
|
4
|
-
|
|
5
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* A cheap look at a file before CoreGraphics is asked to parse it.
|
|
9
|
-
*
|
|
10
|
-
* ------------------------------------------------------------------------
|
|
11
|
-
* IT IS NOT A POISON GUARD, AND iOS DOES NOT NEED ONE.
|
|
12
|
-
* ------------------------------------------------------------------------
|
|
13
|
-
*
|
|
14
|
-
* `PdfPreflight.java` exists for a hard reason: on Android API 24 a `PdfRenderer`
|
|
15
|
-
* constructor that THROWS permanently poisons PDFium for the whole process — one
|
|
16
|
-
* failed open plus a garbage collection and the next successful open segfaults in
|
|
17
|
-
* `CPDF_Document`. So on Android, preflight is a correctness mechanism and its
|
|
18
|
-
* scan window is load-bearing (a bug in it once let a 60 KB encrypted file through
|
|
19
|
-
* and cascaded into eight unrelated failures).
|
|
20
|
-
*
|
|
21
|
-
* CoreGraphics has no such behaviour. MEASURED: `CGPDFDocumentCreateWithProvider`
|
|
22
|
-
* over a `%PDF-1.7` header followed by garbage returns NULL — it logs "failed to
|
|
23
|
-
* find start of cross-reference table" under `CG_PDF_VERBOSE` and returns cleanly
|
|
24
|
-
* — and so does an empty buffer, and a subsequent open of a good document
|
|
25
|
-
* succeeds. There is nothing to protect.
|
|
26
|
-
*
|
|
27
|
-
* ------------------------------------------------------------------------
|
|
28
|
-
* WHAT IT IS FOR: TELLING THREE FAILURES APART.
|
|
29
|
-
* ------------------------------------------------------------------------
|
|
30
|
-
*
|
|
31
|
-
* `CGPDFDocumentCreateWithURL` returning NULL is one signal for "no such file",
|
|
32
|
-
* "no permission", "zero bytes" and "not a PDF", and those want four different
|
|
33
|
-
* `PdfErrorCode`s and four different messages. A host showing "corrupt" for a path
|
|
34
|
-
* that simply does not exist sends somebody looking at the wrong thing. So this
|
|
35
|
-
* runs first, answers the questions the file system can answer, and gets out of
|
|
36
|
-
* the way — every judgement CoreGraphics is better at (encryption, structure,
|
|
37
|
-
* page count) is left to it.
|
|
38
|
-
*/
|
|
39
|
-
@interface PdfCanvasPreflight : NSObject
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Returns YES if `url` is worth handing to CoreGraphics.
|
|
43
|
-
*
|
|
44
|
-
* Checks, in order: the path exists, it is a file rather than a directory, it is
|
|
45
|
-
* readable, it is not empty, and its first bytes contain a `%PDF-` header.
|
|
46
|
-
*
|
|
47
|
-
* THE HEADER SCAN IS A WINDOW, not the first five bytes. The spec allows leading
|
|
48
|
-
* junk before `%PDF-` and real files carry it (an HTTP preamble, a shell wrapper),
|
|
49
|
-
* and every reader in existence tolerates it; Acrobat's own limit is 1024 bytes,
|
|
50
|
-
* which is the window used here. A file with no header in that window gets
|
|
51
|
-
* `corrupt` with a message naming what was looked for, rather than CoreGraphics'
|
|
52
|
-
* silence.
|
|
53
|
-
*/
|
|
54
|
-
+ (BOOL)checkFileURL:(NSURL *)url
|
|
55
|
-
error:(NSError *_Nullable *_Nullable)error
|
|
56
|
-
NS_SWIFT_NAME(check(fileURL:));
|
|
57
|
-
|
|
58
|
-
/** The same header test, for the in-memory `open` path. */
|
|
59
|
-
+ (BOOL)checkData:(NSData *)data
|
|
60
|
-
error:(NSError *_Nullable *_Nullable)error
|
|
61
|
-
NS_SWIFT_NAME(check(_:));
|
|
62
|
-
|
|
63
|
-
@end
|
|
64
|
-
|
|
65
|
-
NS_ASSUME_NONNULL_END
|