Cross-platform native desktop PDF editor with full content editing
Go to file
ai-ad4 17512022e9 feat(spike-C): hb-subset font growth; new glyph renders (§14 step 6)
Implement Spike C: grow an existing embedded subset font with a new glyph
using hb-subset and verify the result, exercising §4.2 resolution ladder
step 1.

SubsetGrowth.cpp runs a three-step scenario with the HarfBuzz subset C API
and FreeType:
1. Build the 'originally embedded' subset of DejaVu Sans with glyphs for
   'Hello' (H,e,l,o).
2. Grow it by adding U+03A9 (Ω) — the character the user typed that wasn't
   in the original subset. Produces a NEW font; original untouched (§4.2:
   'never mutate a font program in place').
3. Verify: grown subset contains the glyph, cmap maps U+03A9 → gid, FreeType
   loads its outline (it renders); original subset does NOT contain it.

Gate MET: original 5 glyphs/4300 bytes → grown 6 glyphs/4488 bytes, new
glyph present and renders. Verified clean under ASan+UBSan. Result and
findings in docs/spike-results/0003-spike-c-subset-growth.md.

Findings: (1) hb-subset growth works and is cheap (+188 bytes/glyph). (2)
HarfBuzz subset API changed across versions — HB_SUBSET_SETS_DROP doesn't
exist in 10.2; pin the baseline (vcpkg manifest does). (3) FT_Get_Char_Index
+ FT_Load_Glyph is the right render-verification pair; the real viewer
check (Acrobat/Preview/Chrome) remains a release gate (§8.3). (4) the
'never mutate in place' rule is honoured by construction (hb_subset_or_fail
returns a new face).

CI: add Spike C to the spike-gates job (libharfbuzz-dev, libfreetype-dev,
fonts-dejavu-core); fails the build on regression.

Signed-off-by: ai-ad4 <ai-ad4@users.noreply.gitea.lm.je>
2026-07-25 20:41:02 +00:00
.gitea/workflows feat(spike-C): hb-subset font growth; new glyph renders (§14 step 6) 2026-07-25 20:41: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-C): hb-subset font growth; new glyph renders (§14 step 6) 2026-07-25 20:41:02 +00:00
packaging chore: initial repository scaffold (§14 steps 1-3, 9) 2026-07-25 20:14:22 +00:00
spike feat(spike-C): hb-subset font growth; new glyph renders (§14 step 6) 2026-07-25 20:41: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.