Skip to content

Spike (#33 phase 1): one drawn-checkbox heuristic shared by iOS and Android - #37

Open
SlyWombat wants to merge 2 commits into
mainfrom
spike/shared-core
Open

Spike (#33 phase 1): one drawn-checkbox heuristic shared by iOS and Android#37
SlyWombat wants to merge 2 commits into
mainfrom
spike/shared-core

Conversation

@SlyWombat

Copy link
Copy Markdown
Owner

Phase 1 of #33, as that issue specifies it: prove the packaging and binding work on
a small operation that already has assertions on every platform, before the
text-edit layer depends on it. detectCheckboxSquares is that operation.

This is a spike, not release work. It is not meant to ride along with the 1.1
payload that just merged. What it produces is the evidence for ADR-002.

The exit criterion from #33

detectCheckboxSquares is deleted from the C#, Kotlin and Swift sources and
implemented once in the shared core, and the existing fixtures assert identical
rects on all three platforms — with the iOS and Android release pipelines green
end to end.

This PR does Android and iOS. Windows is deliberately left out, per the
migration order in #33: it is the only shipping product, it needs an MSVC/CMake
step added to its pipeline to produce megapdf_core.dll, and IPdfEngine should
be preserved as an adapter so no MegaPDF.App code changes. Tracked separately.

What landed

core/megapdf_core.{h,cpp} — the ABI and its one implementation. The rules that
let three toolchains agree:

  • C only. No C++ types cross, no exceptions escape.
  • Handles are void* — pass your FPDF_PAGE straight through. The header
    includes nothing from pdfium, so binding code needs only that one file.
  • Caller-owned buffers, count-then-fill. Keeps JNI and P/Invoke marshalling
    trivial.
  • Coordinates come back in crop space. Getting that wrong is iOS: search highlights and tap targets use MediaBox coordinates on cropped pages #30 exactly, so
    it happens once here instead of in each binding.

Android compiles it into the existing .so (one CMake line; no second binary to
ship, no runtime ABI boundary) and its JNI entry point becomes marshalling only —
which is what engine.cpp's own header comment always claimed it was. iOS compiles
it into the app target and reaches it through a bridging header. Both hand-written
copies of the heuristic are gone.

What CI decides

The existing fixture assertions are the check: CheckboxTest on Android and
CheckboxTests on iOS already assert exact rects from fixture.pdf, and they now
exercise the shared implementation instead of two separate ones. If they still pass
unchanged, the architecture is proven for the rest; if the packaging fights back,
we learned it for the price of one small function.

🤖 Generated with Claude Code

…tforms (#33)

The spike #33 asks for: prove the packaging and binding work on a small
operation that already has assertions everywhere, before the text-edit layer
depends on it. detectCheckboxSquares is that operation.

core/ holds the C ABI and its one implementation. ABI rules so three toolchains
can agree: C only, handles are void* (pass your FPDF_PAGE straight through, the
header includes nothing from pdfium), caller-owned buffers with a count-then-fill
call, and coordinates already converted to crop space — because getting that
wrong is exactly #30, and it should happen once rather than in each binding.

Android compiles it into the existing .so via CMake; the JNI entry point is now
marshalling only, which is what its own header comment always claimed it was.
iOS compiles it into the app target and reaches it through a bridging header.
Both platforms' hand-written copies of the heuristic are deleted.

Windows is deliberately not in this commit: it is the only shipping product and
needs an MSVC/CMake step in its pipeline, so it goes last, with IPdfEngine
preserved as an adapter. Not merged into the release either — this is a spike
whose result feeds ADR-002.
Written from PR #37's results rather than from reasoning, in ADR-001's shape:
21 Android instrumented tests and 37 iOS tests green against one implementation,
+2,140 bytes of APK (+0.014%), one CMake line on Android, a bridging header on
iOS, and both hand-written copies of the heuristic deleted.

Status is PROPOSED, not ACCEPTED, because the Windows leg is unbuilt — and the
spike's most useful finding is *why*: that leg is a distribution decision, not a
coding one. No pdfium import library is vendored (generating one from the DLL
works — 461 symbols, verified), and the local VS 2017 Build Tools have the
compiler but no Windows SDK, so adding a native build step would break local
builds of the only shipping product until someone installs it. Vendor a prebuilt
or require the SDK: that choice belongs to whoever maintains the Windows release,
and it is written up with the recipe in #38.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant