@reekon-tools/react-native-pdf-canvas 0.1.1 → 0.2.1
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 +77 -40
- package/README.md +218 -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/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/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 +27 -7
- package/react-native.config.js +5 -2
- package/scripts/fetch-pdfium.mjs +559 -0
- package/scripts/pdfium-manifest.json +48 -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,33 +1,30 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
#
|
|
3
|
-
# The Android compile gate:
|
|
4
|
-
#
|
|
3
|
+
# The Android compile gate: build and link every Android source in this package
|
|
4
|
+
# WITHOUT gradle, an emulator, or a device. Runs in seconds.
|
|
5
5
|
#
|
|
6
|
-
# WHY THIS EXISTS. A cold gradle build of a consuming app is ~45 minutes
|
|
6
|
+
# WHY THIS EXISTS. A cold gradle build of a consuming app is ~45 minutes and
|
|
7
7
|
# does not reliably produce a runnable app, so the practical alternative to this
|
|
8
|
-
# script is "change JNI and find out on an EAS build".
|
|
9
|
-
# checks cannot be caught any other way short of a device:
|
|
8
|
+
# script is "change JNI and find out on an EAS build". What it checks:
|
|
10
9
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
10
|
+
# 1. The C++ core + JNI compile and LINK into libpdfcanvas.so for arm64 and
|
|
11
|
+
# armv7, in both configurations (standalone / WITH_JSI), against the pinned
|
|
12
|
+
# libpdfium.so and — for WITH_JSI — the react-android AAR's own libjsi.so,
|
|
13
|
+
# with `-Wl,--no-undefined`. A platform function missing at the minSdk, a
|
|
14
|
+
# PDFium symbol the pinned build does not export, or a jsi symbol the app's
|
|
15
|
+
# RN version lacks all fail HERE.
|
|
16
|
+
# 2. The built .so exports every JNI symbol Java will look up.
|
|
17
|
+
# 3. javac: the React-free core (`src/main`), the binding (`src/reactnative`,
|
|
18
|
+
# against the RN classes.jar) and the instrumented suite.
|
|
19
|
+
# 4. JNI SIGNATURES: `javac -h` derives the expected C prototypes from the
|
|
20
|
+
# `native` declarations; force-including that header makes clang compare
|
|
21
|
+
# every definition against its declaration, and the reverse check finds a
|
|
22
|
+
# method declared native with no definition. Both are the class of bug that
|
|
23
|
+
# compiles clean on both sides and fails only as an UnsatisfiedLinkError.
|
|
18
24
|
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
# `target_link_libraries` entry, a platform function that does not exist at the
|
|
23
|
-
# minSdk, or a jsi symbol the app's React Native version does not export all fail
|
|
24
|
-
# HERE. It then checks that the built .so exports every JNI symbol Java expects.
|
|
25
|
-
# What is skipped versus a real build is gradle and cmake orchestration only.
|
|
26
|
-
#
|
|
27
|
-
# WHAT IT IS NOT. It runs no Java, no C++ and no test. Correctness of the
|
|
28
|
-
# rasterizer and of the raster transport is proven by
|
|
29
|
-
# `cd android && ./gradlew connectedDebugAndroidTest` on a device, and nothing
|
|
30
|
-
# here substitutes for that.
|
|
25
|
+
# WHAT IT IS NOT. It runs no Java, no C++ and no test. Rendering correctness is
|
|
26
|
+
# proven by `native/tests` on the host; the JNI seam on a device by
|
|
27
|
+
# `cd android && ./gradlew connectedDebugAndroidTest`.
|
|
31
28
|
#
|
|
32
29
|
# Usage: bash android/tools/compile-gate.sh
|
|
33
30
|
#
|
|
@@ -37,6 +34,7 @@
|
|
|
37
34
|
set -u
|
|
38
35
|
here=$(cd "$(dirname "$0")/.." && pwd) # <repo>/android
|
|
39
36
|
PKG=$here
|
|
37
|
+
ROOT=$(cd "$here/.." && pwd)
|
|
40
38
|
fail=0
|
|
41
39
|
skipped=0
|
|
42
40
|
|
|
@@ -55,7 +53,6 @@ SDK=${ANDROID_SDK_ROOT:-${ANDROID_HOME:-$HOME/AppData/Local/Android/Sdk}}
|
|
|
55
53
|
[ -d "$SDK" ] || SDK=$HOME/Library/Android/sdk
|
|
56
54
|
[ -d "$SDK" ] || SDK=$HOME/Android/Sdk
|
|
57
55
|
|
|
58
|
-
# Newest installed NDK, unless one is pinned.
|
|
59
56
|
NDK=${ANDROID_NDK_HOME:-}
|
|
60
57
|
if [ -z "$NDK" ]; then
|
|
61
58
|
NDK=$(ls -d "$SDK"/ndk/* 2>/dev/null | sort -V | tail -1)
|
|
@@ -68,13 +65,10 @@ for host in windows-x86_64 darwin-x86_64 linux-x86_64; do
|
|
|
68
65
|
done
|
|
69
66
|
done
|
|
70
67
|
|
|
71
|
-
# Newest platform android.jar. -bootclasspath needs a Windows-style path on
|
|
72
|
-
# Windows because javac is a native binary; `cygpath -m` is a no-op elsewhere.
|
|
73
68
|
winpath() { if command -v cygpath >/dev/null 2>&1; then cygpath -m "$1"; else echo "$1"; fi; }
|
|
74
69
|
AJAR=$(ls -d "$SDK"/platforms/android-*/android.jar 2>/dev/null | sort -V | tail -1)
|
|
75
70
|
[ -n "$AJAR" ] && AJAR=$(winpath "$AJAR")
|
|
76
71
|
|
|
77
|
-
# javac 17: the module targets VERSION_17. A JDK 8 javac cannot compile it.
|
|
78
72
|
JAVAC=""
|
|
79
73
|
for cand in "${JAVA_HOME:-}/bin/javac" \
|
|
80
74
|
"/c/Program Files/Android/Android Studio/jbr/bin/javac.exe" \
|
|
@@ -84,8 +78,6 @@ for cand in "${JAVA_HOME:-}/bin/javac" \
|
|
|
84
78
|
[ "${v:-0}" -ge 11 ] 2>/dev/null && JAVAC="$cand" && break
|
|
85
79
|
done
|
|
86
80
|
|
|
87
|
-
# jsi/jsi.h and the react-android classes.jar come from a consuming app's
|
|
88
|
-
# node_modules. RN_ROOT can point straight at one.
|
|
89
81
|
RN=${RN_ROOT:-}
|
|
90
82
|
if [ -z "$RN" ]; then
|
|
91
83
|
for cand in "$here/../node_modules/react-native" \
|
|
@@ -99,11 +91,6 @@ JSI="$RN/ReactCommon/jsi"
|
|
|
99
91
|
OUT=${TMPDIR:-/tmp}/pdfcanvas-gate
|
|
100
92
|
rm -rf "$OUT"; mkdir -p "$OUT"/{standalone,autolinked,androidtest,h,classes,rn}
|
|
101
93
|
|
|
102
|
-
# react-android's classes.jar is inside an AAR in the gradle cache. Needed only
|
|
103
|
-
# for section 3.
|
|
104
|
-
# Extracted WHOLE rather than with a `jni/*` member filter: MSYS unzip extracts
|
|
105
|
-
# nothing for that pattern, which silently loses libjsi.so and turns the
|
|
106
|
-
# WITH_JSI link into a skip. The AAR is a couple of megabytes; just unpack it.
|
|
107
94
|
RNJAR=""
|
|
108
95
|
aar=$(ls -t "$HOME"/.gradle/caches/modules-2/files-2.1/com.facebook.react/react-android/*/*/*-release.aar 2>/dev/null | head -1)
|
|
109
96
|
[ -z "$aar" ] && aar=$(ls -t "$HOME"/.gradle/caches/modules-2/files-2.1/com.facebook.react/react-android/*/*/*-debug.aar 2>/dev/null | head -1)
|
|
@@ -120,104 +107,107 @@ for host in windows-x86_64 darwin-x86_64 linux-x86_64; do
|
|
|
120
107
|
done
|
|
121
108
|
done
|
|
122
109
|
|
|
123
|
-
# libjsi.so ships inside the same AAR, one copy per ABI, already unpacked above.
|
|
124
110
|
JSILIB=""
|
|
125
111
|
[ -f "$OUT/rn/jni/arm64-v8a/libjsi.so" ] && JSILIB="$OUT/rn/jni"
|
|
126
112
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
113
|
+
# PDFium for the two ABIs the gate links. Fetched through the same script the
|
|
114
|
+
# build uses, so the gate links exactly what the AAR will carry.
|
|
115
|
+
PDFIUM="$ROOT/native/.pdfium/android"
|
|
116
|
+
if command -v node >/dev/null 2>&1; then
|
|
117
|
+
(cd "$ROOT" && node scripts/fetch-pdfium.mjs android --abis arm64-v8a,armeabi-v7a >/dev/null) || echo "WARN fetch-pdfium failed; using whatever is at $PDFIUM"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
CORE_SRCS=$(ls "$ROOT"/native/core/src/*.cpp)
|
|
121
|
+
JNI_SRC="$PKG/src/main/cpp/pdfcanvas-jni.cpp"
|
|
122
|
+
INCLUDES="-I$ROOT/native/core/include -I$PDFIUM/include"
|
|
123
|
+
|
|
124
|
+
echo "SDK $SDK"
|
|
125
|
+
echo "NDK ${NDK:-<none>}"
|
|
126
|
+
echo "javac ${JAVAC:-<none>}"
|
|
127
|
+
echo "RN ${RN:-<none>}"
|
|
128
|
+
echo "PDFium $PDFIUM ($(cat "$PDFIUM/.stamp" 2>/dev/null || echo 'not fetched'))"
|
|
131
129
|
echo
|
|
132
130
|
|
|
133
131
|
# ---------------------------------------------------------------- 1. C++
|
|
134
|
-
# Both #if configurations, both pointer widths. 32-bit is not redundant: it is
|
|
135
|
-
# what catches a size_t/jsize/uint64 width slip that arm64 hides.
|
|
136
132
|
abi_dir() { case "$1" in aarch64*) echo arm64-v8a;; armv7a*) echo armeabi-v7a;; esac; }
|
|
137
133
|
|
|
138
|
-
if [ -n "$CLANG" ]; then
|
|
134
|
+
if [ -n "$CLANG" ] && [ -f "$PDFIUM/include/fpdfview.h" ]; then
|
|
139
135
|
for abi in aarch64-linux-android24 armv7a-linux-androideabi24; do
|
|
136
|
+
lib="$PDFIUM/jniLibs/$(abi_dir "$abi")/libpdfium.so"
|
|
137
|
+
if [ ! -f "$lib" ]; then say_skip "cpp+link $abi" "no libpdfium.so for $(abi_dir "$abi")"; continue; fi
|
|
140
138
|
# --no-undefined is the point of linking rather than syntax-checking: it
|
|
141
|
-
# fails on any symbol the platform will not supply at runtime
|
|
142
|
-
# exactly the class of mistake a -fsyntax-only pass waves through and a
|
|
143
|
-
# device then reports as a dlopen failure and a silent base64 fallback.
|
|
139
|
+
# fails on any symbol the platform (or PDFium) will not supply at runtime.
|
|
144
140
|
run "cpp+link standalone $abi" "$CLANG" --target=$abi -std=c++17 -O2 \
|
|
145
|
-
-Wall -Wextra -Werror -shared -fPIC
|
|
146
|
-
"$
|
|
141
|
+
-Wall -Wextra -Werror -frtti -fexceptions -shared -fPIC $INCLUDES \
|
|
142
|
+
-o "$OUT/lib-$abi.so" $CORE_SRCS "$JNI_SRC" "$lib" -llog -Wl,--no-undefined
|
|
147
143
|
|
|
148
144
|
if [ -f "$JSI/jsi/jsi.h" ] && [ -n "$JSILIB" ] && [ -d "$JSILIB/$(abi_dir "$abi")" ]; then
|
|
149
145
|
run "cpp+link WITH_JSI $abi" "$CLANG" --target=$abi -std=c++17 -O2 \
|
|
150
|
-
-Wall -Wextra -Werror -frtti -fexceptions -shared -fPIC \
|
|
146
|
+
-Wall -Wextra -Werror -frtti -fexceptions -shared -fPIC $INCLUDES \
|
|
151
147
|
-DPDFCANVAS_WITH_JSI=1 -I"$JSI" -o "$OUT/lib-jsi-$abi.so" \
|
|
152
|
-
"$
|
|
148
|
+
$CORE_SRCS "$JNI_SRC" "$lib" -llog \
|
|
153
149
|
-L"$JSILIB/$(abi_dir "$abi")" -ljsi -Wl,--no-undefined
|
|
154
150
|
elif [ ! -f "$JSI/jsi/jsi.h" ]; then
|
|
155
|
-
say_skip "cpp+link WITH_JSI $abi"
|
|
156
|
-
"no jsi/jsi.h; set RN_ROOT to a react-native install"
|
|
151
|
+
say_skip "cpp+link WITH_JSI $abi" "no jsi/jsi.h; set RN_ROOT to a react-native install"
|
|
157
152
|
else
|
|
158
|
-
say_skip "cpp+link WITH_JSI $abi"
|
|
159
|
-
"no libjsi.so for this ABI in the react-android AAR"
|
|
153
|
+
say_skip "cpp+link WITH_JSI $abi" "no libjsi.so for this ABI in the react-android AAR"
|
|
160
154
|
fi
|
|
161
155
|
done
|
|
162
156
|
|
|
163
|
-
# The gate links with an explicit
|
|
164
|
-
# equivalent line were dropped from CMakeLists.txt
|
|
165
|
-
|
|
166
|
-
cml="$PKG/src/jsi/cpp/CMakeLists.txt"
|
|
157
|
+
# The gate links with an explicit list, so it would keep passing if the
|
|
158
|
+
# equivalent line were dropped from CMakeLists.txt. Assert the two agree.
|
|
159
|
+
cml="$PKG/src/main/cpp/CMakeLists.txt"
|
|
167
160
|
missing_link=""
|
|
168
|
-
for lib in
|
|
161
|
+
for lib in pdfium log; do
|
|
169
162
|
grep -q "target_link_libraries.*[ (]$lib[ )]" "$cml" || missing_link="$missing_link $lib"
|
|
170
163
|
done
|
|
171
164
|
if [ -z "$missing_link" ]; then
|
|
172
165
|
echo "PASS CMakeLists links what this gate links"
|
|
173
166
|
else
|
|
174
|
-
echo "FAIL this gate links$missing_link but CMakeLists.txt does not"
|
|
175
|
-
fail=1
|
|
167
|
+
echo "FAIL this gate links$missing_link but CMakeLists.txt does not"; fail=1
|
|
176
168
|
fi
|
|
177
169
|
|
|
178
|
-
# The
|
|
179
|
-
#
|
|
170
|
+
# The core source list in pdfcanvas-core.cmake must name every file that
|
|
171
|
+
# exists, or a platform build silently misses one.
|
|
172
|
+
for f in $CORE_SRCS; do
|
|
173
|
+
grep -q "$(basename "$f")" "$ROOT/native/core/pdfcanvas-core.cmake" \
|
|
174
|
+
|| { echo "FAIL native/core/src/$(basename "$f") is not listed in pdfcanvas-core.cmake"; fail=1; }
|
|
175
|
+
done
|
|
176
|
+
|
|
180
177
|
if [ -n "$NM" ] && [ -f "$OUT/lib-aarch64-linux-android24.so" ]; then
|
|
181
178
|
exported=$("$NM" -D --defined-only "$OUT/lib-aarch64-linux-android24.so" 2>/dev/null \
|
|
182
|
-
| grep -c '
|
|
183
|
-
if [ "${exported:-0}" -ge
|
|
184
|
-
echo "PASS the linked .so exports $exported
|
|
179
|
+
| grep -c 'Java_tools_reekon_pdfcanvas_PdfCanvasNative_')
|
|
180
|
+
if [ "${exported:-0}" -ge 13 ]; then
|
|
181
|
+
echo "PASS the linked .so exports $exported Java_tools_reekon_pdfcanvas_PdfCanvasNative_* symbols"
|
|
185
182
|
else
|
|
186
|
-
echo "FAIL the linked .so exports only ${exported:-0} JNI symbols (expected >=
|
|
187
|
-
fail=1
|
|
183
|
+
echo "FAIL the linked .so exports only ${exported:-0} JNI symbols (expected >= 13)"; fail=1
|
|
188
184
|
fi
|
|
189
185
|
else
|
|
190
186
|
say_skip "exported JNI symbols" "no llvm-nm, or nothing linked"
|
|
191
187
|
fi
|
|
192
|
-
|
|
188
|
+
elif [ -z "$CLANG" ]; then
|
|
193
189
|
say_skip "cpp (all)" "no NDK clang++ found; set ANDROID_NDK_HOME"
|
|
190
|
+
else
|
|
191
|
+
say_skip "cpp (all)" "no PDFium headers at $PDFIUM; run node scripts/fetch-pdfium.mjs android"
|
|
194
192
|
fi
|
|
195
193
|
|
|
196
|
-
# ---------------------------------------------------------------- 2/3
|
|
194
|
+
# ---------------------------------------------------------------- 2/3. Java
|
|
197
195
|
if [ -n "$JAVAC" ] && [ -n "$AJAR" ]; then
|
|
198
|
-
|
|
199
|
-
# API surface. -Werror here because this half is meant to stay clean.
|
|
200
|
-
run "javac standalone (main+jsi)" \
|
|
196
|
+
run "javac standalone (main)" \
|
|
201
197
|
"$JAVAC" -proc:none -nowarn -Werror -d "$OUT/standalone" -bootclasspath "$AJAR" \
|
|
202
198
|
-source 8 -target 8 \
|
|
203
|
-
"$PKG"/src/main/java/tools/reekon/pdfcanvas/*.java
|
|
204
|
-
"$PKG"/src/jsi/java/tools/reekon/pdfcanvas/jsi/*.java
|
|
199
|
+
"$PKG"/src/main/java/tools/reekon/pdfcanvas/*.java
|
|
205
200
|
|
|
206
|
-
# Autolinked build: adds src/reactnative. Its lambdas need a real java.base,
|
|
207
|
-
# so android.jar moves from -bootclasspath to -cp.
|
|
208
201
|
if [ -n "$RNJAR" ]; then
|
|
209
202
|
run "javac autolinked (+reactnative)" \
|
|
210
203
|
"$JAVAC" -proc:none -nowarn -d "$OUT/autolinked" -cp "$AJAR;$RNJAR" \
|
|
211
204
|
"$PKG"/src/main/java/tools/reekon/pdfcanvas/*.java \
|
|
212
|
-
"$PKG"/src/jsi/java/tools/reekon/pdfcanvas/jsi/*.java \
|
|
213
205
|
"$PKG"/src/reactnative/java/tools/reekon/pdfcanvas/rn/*.java
|
|
214
206
|
else
|
|
215
207
|
say_skip "javac autolinked (+reactnative)" \
|
|
216
208
|
"no react-android AAR in the gradle cache; build a consuming app once to populate it"
|
|
217
209
|
fi
|
|
218
210
|
|
|
219
|
-
# The instrumented suite, against the standalone classes it tests. Compiling
|
|
220
|
-
# it is how a change to the rasterizer's API is caught before a device run.
|
|
221
211
|
TESTCP=""
|
|
222
212
|
for a in androidx.test/core androidx.test/monitor androidx.test/runner androidx.test.ext/junit; do
|
|
223
213
|
aa=$(ls -t "$HOME"/.gradle/caches/modules-2/files-2.1/$a/*/*/*.aar 2>/dev/null | head -1)
|
|
@@ -241,36 +231,26 @@ else
|
|
|
241
231
|
say_skip "javac (all)" "need a JDK 11+ javac and an SDK platform android.jar"
|
|
242
232
|
fi
|
|
243
233
|
|
|
244
|
-
# ----------------------------------------------------------------
|
|
245
|
-
|
|
246
|
-
# from the Java `native` declarations; force-including that header makes clang
|
|
247
|
-
# compare every definition against its declaration, so a drifted parameter list
|
|
248
|
-
# or return type is a compile error instead of an UnsatisfiedLinkError on a
|
|
249
|
-
# device. The loop then checks the reverse: a method declared `native` in Java
|
|
250
|
-
# with no C++ definition compiles clean everywhere and fails only at runtime.
|
|
251
|
-
if [ -n "$JAVAC" ] && [ -n "$AJAR" ] && [ -n "$CLANG" ] && [ -f "$JSI/jsi/jsi.h" ]; then
|
|
234
|
+
# ---------------------------------------------------------------- 4. JNI
|
|
235
|
+
if [ -n "$JAVAC" ] && [ -n "$AJAR" ] && [ -n "$CLANG" ] && [ -f "$PDFIUM/include/fpdfview.h" ]; then
|
|
252
236
|
if "$JAVAC" -proc:none -nowarn -d "$OUT/classes" -h "$OUT/h" -bootclasspath "$AJAR" \
|
|
253
237
|
-source 8 -target 8 \
|
|
254
|
-
"$PKG"/src/main/java/tools/reekon/pdfcanvas/*.java
|
|
255
|
-
"$PKG"/src/jsi/java/tools/reekon/pdfcanvas/jsi/*.java >/dev/null 2>&1; then
|
|
238
|
+
"$PKG"/src/main/java/tools/reekon/pdfcanvas/*.java >/dev/null 2>&1; then
|
|
256
239
|
for abi in aarch64-linux-android24 armv7a-linux-androideabi24; do
|
|
257
|
-
# -fsyntax-only
|
|
258
|
-
#
|
|
240
|
+
# -fsyntax-only on purpose: this pass compares declarations; the link is
|
|
241
|
+
# already covered by section 1.
|
|
259
242
|
run "jni prototypes match $abi" "$CLANG" --target=$abi -std=c++17 -fsyntax-only \
|
|
260
|
-
-Wall -Wextra -Werror -frtti -fexceptions
|
|
261
|
-
-I"$OUT/h" -include
|
|
262
|
-
"$PKG/src/jsi/cpp/pdfcanvas-jsi.cpp"
|
|
243
|
+
-Wall -Wextra -Werror -frtti -fexceptions $INCLUDES \
|
|
244
|
+
-I"$OUT/h" -include tools_reekon_pdfcanvas_PdfCanvasNative.h "$JNI_SRC"
|
|
263
245
|
done
|
|
264
246
|
declared=$(grep -o 'Java_[A-Za-z0-9_]*' "$OUT"/h/*.h | sed 's/.*://' | sort -u)
|
|
265
247
|
n=0; missing=""
|
|
266
248
|
for m in $declared; do
|
|
267
249
|
n=$((n + 1))
|
|
268
|
-
grep -q "
|
|
250
|
+
grep -q "${m}(" "$JNI_SRC" || missing="$missing $m"
|
|
269
251
|
done
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if [ "$n" -lt 7 ]; then
|
|
273
|
-
echo "FAIL the JNI gate found only $n declared native methods (expected >= 7)"; fail=1
|
|
252
|
+
if [ "$n" -lt 13 ]; then
|
|
253
|
+
echo "FAIL the JNI gate found only $n declared native methods (expected >= 13)"; fail=1
|
|
274
254
|
elif [ -n "$missing" ]; then
|
|
275
255
|
echo "FAIL declared native in Java, undefined in C++:$missing"; fail=1
|
|
276
256
|
else
|
|
@@ -280,7 +260,7 @@ if [ -n "$JAVAC" ] && [ -n "$AJAR" ] && [ -n "$CLANG" ] && [ -f "$JSI/jsi/jsi.h"
|
|
|
280
260
|
echo "FAIL could not generate JNI headers"; fail=1
|
|
281
261
|
fi
|
|
282
262
|
else
|
|
283
|
-
say_skip "jni signature gate" "needs javac, android.jar, NDK clang++ and
|
|
263
|
+
say_skip "jni signature gate" "needs javac, android.jar, NDK clang++ and the PDFium headers together"
|
|
284
264
|
fi
|
|
285
265
|
|
|
286
266
|
echo "---"
|
package/dist/controller.d.ts
CHANGED
|
@@ -90,6 +90,20 @@ export interface PdfControllerOptions {
|
|
|
90
90
|
* epoch never spawns a lane it has no work for.
|
|
91
91
|
*/
|
|
92
92
|
maxConcurrentRenders?: number;
|
|
93
|
+
/**
|
|
94
|
+
* Whether tiles draw the PDF's own annotations — highlights, callouts,
|
|
95
|
+
* stamps, arrows, AND form fields — into the raster.
|
|
96
|
+
*
|
|
97
|
+
* DEFAULT TRUE: a page on the canvas should look like the same page in any
|
|
98
|
+
* other viewer, which is what the field reports that prompted this were
|
|
99
|
+
* about ("the annotations are missing"). It used to be hardcoded false on the
|
|
100
|
+
* theory that the Skia layer draws the app's OWN annotations and a PDF-embedded
|
|
101
|
+
* copy would double-draw. That theory is only true for a host that IMPORTS
|
|
102
|
+
* PDF annotations into its own layer — none does today — and such a host is
|
|
103
|
+
* who this switch is for: set it false and the tiles carry the content stream
|
|
104
|
+
* alone, on every backend, identically.
|
|
105
|
+
*/
|
|
106
|
+
annotations?: boolean;
|
|
93
107
|
/** Injected so tests drive a fake clock. Nothing below calls Date.now. */
|
|
94
108
|
now?: () => number;
|
|
95
109
|
/** Injected so tests drive a fake clock. Nothing below calls setTimeout. */
|
package/dist/controller.js
CHANGED
|
@@ -95,6 +95,7 @@ function toPdfError(cause) {
|
|
|
95
95
|
}
|
|
96
96
|
export function createPdfController(options) {
|
|
97
97
|
const { handle, policy, ingest, cache, allowedPages } = options;
|
|
98
|
+
const drawAnnotations = options.annotations ?? true;
|
|
98
99
|
const now = options.now ?? DEFAULT_NOW;
|
|
99
100
|
const schedule = options.schedule ?? DEFAULT_SCHEDULE;
|
|
100
101
|
const backendId = options.backendId ?? 'unknown';
|
|
@@ -417,9 +418,9 @@ export function createPdfController(options) {
|
|
|
417
418
|
height: item.docRect.height / info.layoutScale,
|
|
418
419
|
},
|
|
419
420
|
scale: item.scale * info.layoutScale,
|
|
420
|
-
//
|
|
421
|
-
// PDF
|
|
422
|
-
annotations:
|
|
421
|
+
// See `PdfControllerOptions.annotations`: true unless the host
|
|
422
|
+
// draws the PDF's annotations itself.
|
|
423
|
+
annotations: drawAnnotations,
|
|
423
424
|
background: 'white',
|
|
424
425
|
}, state.abort.signal);
|
|
425
426
|
}
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The native default rasterizer.
|
|
3
3
|
*
|
|
4
|
-
* BOTH PLATFORMS
|
|
5
|
-
*
|
|
6
|
-
* is
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* the pure core, the Skia ingest path and the
|
|
10
|
-
*
|
|
11
|
-
* ONE NATIVE MODULE NAME FOR BOTH PLATFORMS (`PdfCanvas`), one wire format, and
|
|
12
|
-
* therefore one lookup. What differs is which adapter wraps it, because the
|
|
13
|
-
* capabilities and the alpha encoding differ — see `./native-bridge.ts`.
|
|
4
|
+
* ONE NATIVE MODULE NAME FOR BOTH PLATFORMS (`PdfCanvas`), one wire format, one
|
|
5
|
+
* adapter, one engine. `createNativeRasterizer` is pure and injectable, and this
|
|
6
|
+
* file is the only place a real native module is resolved. On any build where
|
|
7
|
+
* the module is absent — a host that skipped autolinking, a platform neither
|
|
8
|
+
* binding knows — the self-describing placeholder is returned, failing at
|
|
9
|
+
* `open()` rather than at import, so the pure core, the Skia ingest path and the
|
|
10
|
+
* fake backend all keep working.
|
|
14
11
|
*/
|
|
15
12
|
import type { PageRasterizer } from '../types.js';
|
|
16
13
|
export * from './index.js';
|
|
17
|
-
export * from './
|
|
18
|
-
export * from './ios.js';
|
|
14
|
+
export * from './native.js';
|
|
19
15
|
export declare const getDefaultRasterizer: () => PageRasterizer;
|
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The native default rasterizer.
|
|
3
3
|
*
|
|
4
|
-
* BOTH PLATFORMS
|
|
5
|
-
*
|
|
6
|
-
* is
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* the pure core, the Skia ingest path and the
|
|
10
|
-
*
|
|
11
|
-
* ONE NATIVE MODULE NAME FOR BOTH PLATFORMS (`PdfCanvas`), one wire format, and
|
|
12
|
-
* therefore one lookup. What differs is which adapter wraps it, because the
|
|
13
|
-
* capabilities and the alpha encoding differ — see `./native-bridge.ts`.
|
|
4
|
+
* ONE NATIVE MODULE NAME FOR BOTH PLATFORMS (`PdfCanvas`), one wire format, one
|
|
5
|
+
* adapter, one engine. `createNativeRasterizer` is pure and injectable, and this
|
|
6
|
+
* file is the only place a real native module is resolved. On any build where
|
|
7
|
+
* the module is absent — a host that skipped autolinking, a platform neither
|
|
8
|
+
* binding knows — the self-describing placeholder is returned, failing at
|
|
9
|
+
* `open()` rather than at import, so the pure core, the Skia ingest path and the
|
|
10
|
+
* fake backend all keep working.
|
|
14
11
|
*/
|
|
15
|
-
import {
|
|
16
|
-
import { createIosRasterizer } from './ios.js';
|
|
12
|
+
import { createNativeRasterizer } from './native.js';
|
|
17
13
|
import { createMissingBackendRasterizer } from './index.js';
|
|
18
14
|
export * from './index.js';
|
|
19
|
-
export * from './
|
|
20
|
-
export * from './ios.js';
|
|
15
|
+
export * from './native.js';
|
|
21
16
|
const MISSING = createMissingBackendRasterizer('missing-native', 'The PdfCanvas native module was not found. On iOS that means the pod is ' +
|
|
22
17
|
'not in the build (run `pod install` after adding the package, and check ' +
|
|
23
18
|
'that `PdfCanvas` appears in Podfile.lock); on Android it means ' +
|
|
24
|
-
'autolinking did not register PdfCanvasPackage.'
|
|
19
|
+
'autolinking did not register PdfCanvasPackage. Either way the app binary ' +
|
|
20
|
+
'predates this package or was built without it — an OTA update cannot add ' +
|
|
21
|
+
'a native module.');
|
|
25
22
|
/**
|
|
26
23
|
* `require`, not `import`, and wrapped in a try.
|
|
27
24
|
*
|
|
@@ -59,9 +56,8 @@ function loadNativeModule() {
|
|
|
59
56
|
* reopen a document, so the default must not be a fresh object per call.
|
|
60
57
|
*
|
|
61
58
|
* IT ALSO NEGOTIATES THE TRANSPORT, which is why "once" matters more than
|
|
62
|
-
* tidiness: `createNativeRasterizer` probes the JSI path at construction, and
|
|
63
|
-
*
|
|
64
|
-
* fresh rasterizer per call would re-run the probe, and each run parks a slot.
|
|
59
|
+
* tidiness: `createNativeRasterizer` probes the JSI path at construction, and
|
|
60
|
+
* each run parks a probe slot. A fresh rasterizer per call would re-run it.
|
|
65
61
|
*
|
|
66
62
|
* NAME COLLISION, deliberate and unresolved here: `react/usePdfDocument.ts`
|
|
67
63
|
* exports a registry accessor with this same name and a DIFFERENT meaning
|
|
@@ -74,7 +70,5 @@ function loadNativeModule() {
|
|
|
74
70
|
const resolved = loadNativeModule();
|
|
75
71
|
const DEFAULT = resolved === null
|
|
76
72
|
? MISSING
|
|
77
|
-
: resolved.os
|
|
78
|
-
? createIosRasterizer(resolved.module)
|
|
79
|
-
: createAndroidRasterizer(resolved.module);
|
|
73
|
+
: createNativeRasterizer(resolved.module, { platform: resolved.os });
|
|
80
74
|
export const getDefaultRasterizer = () => DEFAULT;
|