Cross-platform native desktop PDF editor with full content editing
Go to file
ai-ad4 91ae2077fa feat(spike-B1): glyph→Unicode ladder on real embedded font; 98% coverage (§4.1 step 1)
Implement Spike B step 1 — the highest-risk reconstruction step, not covered
by Spike B's synthetic corpus (where Unicode was known by construction).

GlyphUnicode.cpp exercises the §4.1 step 1 priority ladder on a real PDF's
embedded font:
- Step 1 (ToUnicode): parses the CMap's beginbfchar sections via QPDF into a
  code→Unicode map. Confidence 1.0 (authoritative).
- Step 4 (cmap fallback): for glyphs the ToUnicode didn't cover, walks the
  embedded font's cmap via FreeType (FT_Get_First_Char/Next_Char) to
  reverse-lookup gid→codepoint. Confidence 0.7.
- Assembles per-glyph mappings with provenance + confidence — the same
  confidence the production UI uses to underline low-confidence characters.

Gate MET on /usr/share/doc/shared-mime-info/shared-mime-info-spec.pdf: 50
glyphs via ToUnicode (conf 1.0), 37 via cmap fallback (conf 0.7), 1
unmapped, coverage 98.4%, avg confidence 0.818. Verified clean under
ASan+UBSan. Result in docs/spike-results/0006-spike-b1-glyph-unicode.md.

Findings: (1) the ToUnicode path works on real embedded fonts (50/62 at
confidence 1.0). (2) the FreeType cmap fallback recovers the rest (37 at
0.7). (3) the confidence signal is meaningful — 0.7 vs 1.0 falls out of
which ladder step resolved the glyph. (4) QPDF+FreeType cover steps 1 and 4;
steps 2-3 (Encoding/Differences/AGL, CIDSystemInfo) and bfrange/CID-keyed
ToUnicode parsing remain M4 work.

Combined with Spike B (F1=0.963), the reconstruction story is de-risked:
the pipeline reconstructs paragraphs from glyph runs, and glyph runs
resolve to Unicode via the ladder. The M4 text-editing milestone has its
foundation.

CI: add Spike B1 to the spike-gates job (shared-mime-info for the test PDF).

Signed-off-by: ai-ad4 <ai-ad4@users.noreply.gitea.lm.je>
2026-07-25 20:57:02 +00:00
.gitea/workflows feat(spike-B1): glyph→Unicode ladder on real embedded font; 98% coverage (§4.1 step 1) 2026-07-25 20:57:02 +00:00
LICENSES chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
ci chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
cmake chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
docs feat(spike-B1): glyph→Unicode ladder on real embedded font; 98% coverage (§4.1 step 1) 2026-07-25 20:57:02 +00:00
packaging chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
spike feat(spike-B1): glyph→Unicode ladder on real embedded font; 98% coverage (§4.1 step 1) 2026-07-25 20:57:02 +00:00
src chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
test fix(spike-A): adapt to installed QPDF 12.2 API; fix use-after-free 2026-07-25 20:30:37 +00:00
.clang-format chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.clang-tidy chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.editorconfig chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.gitattributes chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.gitignore chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.gitleaks.toml chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
.pre-commit-config.yaml chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
CMakeLists.txt chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
CMakePresets.json chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
CODEOWNERS chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
CONTRIBUTING.md chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
README.md chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
REUSE.toml build(license): convert dep5 to REUSE.toml; record Spike A result 2026-07-25 20:30:43 +00:00
SECURITY.md chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
TRADEMARK.md build(license): convert dep5 to REUSE.toml; record Spike A result 2026-07-25 20:30:43 +00:00
vcpkg-configuration.json chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
vcpkg.json chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00

README.md

FreePDFEditor

A cross-platform native desktop PDF editor with a true WYSIWYG interface and full content editing: edit existing text with reflow, replace images, manipulate vector objects, plus annotations, forms, signatures, and page assembly.

  • Stack: C++20, Qt 6.7 (Widgets shell, custom canvas), CMake, vcpkg.
  • License: GPL-3.0-or-later (see LICENSES/GPL-3.0-or-later.txt). Qt is dynamically linked under LGPL-3.0.
  • Targets: Windows 10+, macOS 12+ (Intel + Apple Silicon), Linux (X11/Wayland).

This repository contains the source and build infrastructure. The full engineering plan and roadmap live in docs/plan.md; architecture decision records are under docs/adr/.

Status

Pre-M0. This is the initial repository scaffold described in §14 of the plan: CMake + vcpkg skeleton, governance docs, CI matrix, packaging pipeline, an empty-window application shell, the pixel-diff harness scaffolding, and the Spike A (QPDF verbatim round-trip) harness. The feasibility spikes that gate the project run on top of this scaffolding.

Building

cmake --preset default
cmake --build --preset default
ctest --preset default

See CONTRIBUTING.md for the full build setup, gate matrix, and coding standard.

Source control

All code is developed on the project Gitea instance at https://gitea.lm.je/ai-ad4/freepdfeditor per docs/plan.md §13. See SECURITY.md for vulnerability reporting.