GlyphPDF v1.5.0 — Professional PDF Workstation

A high-performance desktop PDF editor built with C++17 and Qt 6. Designed for professional environments with a focus on precision, security, and direct document manipulation — with no telemetry, no subscription, and no cloud dependency.
Install
You need nothing but the app itself. No MSYS2, no Qt, no compilers, no runtime to install separately — every dependency (Qt 6, the PDF/OCR engines, the C++ and Visual C++ runtimes, the OCR models) is bundled inside the download. Just get it and run it.
| Option | Download | How to run |
|---|
| Installer (recommended) | GlyphPDF-1.5.0-x64.msi | Double-click → Next → Finish. Adds Start-menu & desktop shortcuts and a "PDF Document — GlyphPDF" Open-With entry. |
| Portable (no install) | GlyphPDF-1.5.0-x64-portable.zip | Unzip anywhere — including a USB stick — and run GlyphPDF.exe. Nothing is written to the registry. |
A winget package (Glyph.GlyphPDF) will follow once releases are code-signed.
System requirements: Windows 10 (version 1607+) or Windows 11, 64-bit. 4 GB RAM recommended for OCR on large documents. That's the entire list.
Every release is published with a .sha256 file so you can verify the download integrity:
Get-FileHash .\GlyphPDF-1.5.0-x64.msi -Algorithm SHA256
Features
Document Editing
- Text editing with inline support, including letter spacing, line spacing and opacity
- Image move, resize, rotate by angle, restack and opacity, written into the PDF
- Full annotation suite (highlights, underlines, notes, stamps, shapes, pencil)
- Forms: text fields, checkboxes, radio buttons, dropdowns, date/numeric/calculated fields
- Form scripts: AcroForm Calculate, Format, Keystroke and Validate scripts run in a sandboxed JavaScript runtime (quickjs-ng) with a CPU deadline
- Page operations: rotate, crop, resize, reorder, insert, extract, split
- Headers, footers, page numbers, Bates numbering
- Text and image watermarks
Security & Signing
- AES-256 password encryption
- Certificate-based encryption (multi-recipient, with a recipient picker)
- PAdES B-LT/B-LTA digital signatures with DSS/VRI, a certify selector and visible signature appearances
- Signature picker: Draw, Type or Upload (each saved as a real PDF annotation)
- Prepare signing requests for other signers (Protect ▸ Sign ▸ Prepare Request)
- Secure redaction (content stream excision, never black rectangles), with a proof step that refuses to certify what it cannot verify
- Document sanitization (15+ vectors)
- SHA-256 only for signature hashing
- Machine policy for administrators: managed settings are always shown as "Managed by policy"
OCR
- Tesseract and RapidOCR PP-OCRv5 engines
- Preprocessing pipeline (deskew, binarize, denoise)
- ROVER word-level multi-engine merge
- Word-level review before accepting OCR text
Accessibility
- Accessibility checker with jump-to-issue rows (including reading order)
- Tag Document: builds a structure tree for untagged documents while preserving images and marked content
Review & Compare
- Comments filter, table view and CSV export
- Printable review summary: comments grouped by page, with status and totals
- Document comparison with page alignment and change-type filters
Conversion & Batch
- PDF to Word (.docx), Excel (.xlsx, real table columns), HTML, images, CSV, text
- Batch processing with inline error reporting
- Batch presets: Bates numbering, rename on conflict, stop on failure, import/export, per-step size report, hot-folder ingest, and a multi-step preset editor
- Export presets (High Quality PDF/A, Web Optimized, Legal Archive)
Print & Export
- Print preview with page setup (paper size, orientation, margins, scaling)
- Export presets panel with create/edit/delete support
UI
- Task-organized ribbon (Home, View, Edit, Pages, Comment, Review, Convert, Forms, Protect and more)
- Single, Continuous and Two-Page layouts; Presentation and Full Screen
- Dark, Light, and High Contrast themes; Eye Care and Night Mode reading modes
- Right-to-left layout option
- Drag-and-drop PDF opening
- Recent files (max 20)
- AI Chat panel (local Ollama only — no document content leaves the machine)
- Find & Replace with redact-all option
- Full keyboard accessibility (F6 region cycling, F1 help)
Localization
GlyphPDF ships in English. Arabic, French, and German translations are planned for a future release (translation scaffolding — 1394 strings each — is in place; human-translated packages are pending commissioning).
Auto-Update
- JSON manifest-based update checker
- SHA-256 verified downloads
- User consent required at every stage
- Dormant until a code-signed release ships: the updater refuses unsigned installers by design
Technical Architecture
pdfws_core (interfaces, ToolId, AppContext, commands base)
pdfws_engines (PoDoFo, PDFium, qpdf, OCR, conversion)
pdfws_commands (undo commands)
pdfws_ui (MainWindow, controllers, modes, ribbon, dialogs)
PdfWorkstation (main.cpp + Bootstrapper)
Framework: Qt 6.11.x (Core, Gui, Widgets, Pdf, PdfWidgets, PrintSupport, Svg, Network, Concurrent, Test) — installed via MSYS2 ucrt64 pacman
Engines:
PdfEditorEngine — PoDoFo integration for structure manipulation, encryption, annotations
RenderCache — PDFium-backed 3-tier LRU cache (256 MB, tiled rendering, prefetch)
SignatureManager — PAdES signing, validation, TSA
UpdateChecker — Async manifest-based auto-update with SHA-256 verification
Dependencies: PoDoFo, PDFium, qpdf, quickjs-ng, OpenSSL, Tesseract, Leptonica, LibXml2, Freetype, Zlib — all via MSYS2 ucrt64 pacman (except PDFium prebuilt + ONNX Runtime bundled). quickjs-ng (mingw-w64-ucrt-x86_64-quickjs-ng, MIT) powers run-side AcroForm Calculate/Format script execution; when absent the build stays green and the capability is disclosed honestly via CapabilityRegistry. The runtime links libqjs-0.dll — shipped beside the executable like the other MSYS2 runtime DLLs.
Building from Source (Developers only)
> End users: skip this entire section. Everything below is for compiling
> GlyphPDF from source. If you just want to use the app, see Install
> above — the released MSI and portable ZIP already contain every dependency
> listed here. Nothing in this section is something a user ever installs.
Prerequisites (build-time toolchain)
> Note: We use the ucrt64 environment (not mingw64) because qt6-pdf (required for the PDF viewer) is only packaged for ucrt64. UCRT is the modern Universal C Runtime, system-native on all Windows 10+ installs.
Vendored binary dependencies (required)
Three untracked binary trees must exist before configuring; a fresh clone
or worktree does not have them:
| Tree | What | How staged |
|---|
third_party/podofo/install/ | PoDoFo 1.1.0 (DLL + CMake config) built from source with the ucrt64 toolchain | bootstrap script or CI builds it from the 1.1.0 tag |
third_party/pdfium/bin/pdfium.dll | PDFium runtime, chromium/7834 (checksum-pinned; matches the vendored import lib - see third_party/pdfium/PROVENANCE.md) | downloaded |
onnxruntime-win-x64-1.17.3/ | ONNX Runtime 1.17.3 (secondary OCR, HAS_RAPIDOCR) | downloaded |
One command provisions (or checks) all three:
scripts/bootstrap-vendor-deps.sh check # verify
scripts/bootstrap-vendor-deps.sh # install what is missing
> Warning: without third_party/podofo/install, CMake silently falls
> back to MSYS2's podofo 0.10.4, which is API-incompatible with this source,
> and the test binaries then fail with 0xc0000135 (missing DLLs). The
> configure log now warns loudly about the substitution and release
> configurations (-DGLYPHPDF_RELEASE_BUILD=ON) hard-fail instead. The CI
> workflows (.github/workflows/ci.yml, release.yml) run the same pinned
> steps on a cache miss.
Build (Windows + MSYS2)
Open the MSYS2 UCRT64 shell (C:\msys64\ucrt64.exe) or any shell with C:\msys64\ucrt64\bin on PATH:
cd glyph-pdf # your clone
mkdir -p build && cd build
cmake .. -G "Ninja"
cmake --build . --parallel 8
Or from PowerShell with MSYS2 ucrt64 on PATH:
$env:PATH = 'C:\msys64\ucrt64\bin;' + $env:PATH
cd glyph-pdf # your clone
cmake -B build -G "Ninja"
cmake --build build --parallel 8
> Git Bash users: put C:\msys64\ucrt64\bin first on PATH. Git for
> Windows ships its own older zlib1.dll / libstdc++-6.dll in
> /mingw64/bin; if that directory comes first, Qt's rcc fails during
> configure with 0xc0000139 (entry point not found).
Optional external tools (two features)
Two optional features use external programs. Both are detected at runtime — the
app finds them automatically if they're on the machine (bundled alongside GlyphPDF, on the
PATH, in Program Files, or in the registry), with no configuration. Both degrade
gracefully: the app runs fine without them and offers a one-click download when you first
use the feature.
| Feature | External tool | How it's found | Without it |
|---|
| PDF/A conformance validation | veraPDF (AGPL-3.0, subprocess only) | bundled verapdf/, GLYPHPDF_VERAPDF env var, or PATH | In-app prompt to download veraPDF |
Office → PDF import (.docx, .xlsx, .pptx, .odt) | LibreOffice (soffice) | bundled libreoffice/, PATH, Program Files, or registry | In-app prompt to download LibreOffice |
Neither is bundled in the default installer (veraPDF ships its own ~150 MB Java runtime;
LibreOffice is ~400 MB). To bundle veraPDF anyway, drop its CLI tree at third_party/verapdf/
before running packaging/build-msi.bat — deploy.ps1 stages it and the app auto-detects it.
Why MSYS2 ucrt64?
GlyphPDF migrated from a hybrid Qt-installer + vcpkg setup to fully MSYS2-native in v1.0.0 development. This eliminates the libstdc++/libwinpthread ABI mismatch that previously required carefully-chosen DLL mixes in the build directory. Single coherent toolchain (GCC 16.x + Qt 6.11 + all deps from pacman), single source of truth for dependency versions, easier maintenance via pacman -Syu.
Building the installer + portable ZIP
To produce the distributable artifacts yourself (the same ones on the Releases page):
cd packaging
build-msi.bat
This runs the full pipeline — compile → deploy.ps1 (stages every runtime DLL, the
VC++ runtime, ONNX models and tessdata into a self-contained tree) → WiX MSI and
portable ZIP, each with a SHA-256 checksum, written to dist/. The MSI registers .pdf
file associations via OpenWithProgids (it does not hijack the default handler).
Two prerequisites the repository cannot provide:
- The OCR models (
models/ppocrv5/, models/pp_doclayout/) are not in the repository,
and deploy.ps1 refuses to stage a payload without them.
- A code-signing certificate. The pipeline signs the EXE and the MSI and has a hard
publish gate.
build-msi.ps1 -SkipSigning produces a local test build only; such
artifacts must never be published.
Testing
set QT_QPA_PLATFORM=offscreen
cd build
ctest --output-on-failure -j6
The suite has 189 registered CTest suites: 188 run, and one probe is deliberately
disabled. They cover:
- the PDF engines;
- save and recovery safety;
- redaction and its proofs;
- signatures and certificate encryption;
- form scripts;
- accessibility tagging;
- OCR;
- conversion;
- batch presets;
- the UI, including
TestViewParity, which characterizes every view mode of the current interface.
Every test gets its own temporary directory, so parallel runs (-j) don't share temp state.
Filter by label to run a subset, for example ctest -L security or ctest -L redaction.
Suites that need the (untracked) OCR models skip themselves when the models are absent.
Run directly from Git Bash, a test executable may print nothing to the console. Use
TestName.exe -o result.txt,txt to capture its QtTest output.
Keyboard Shortcuts
| Shortcut | Action |
|---|
| Ctrl+O | Open document |
| Ctrl+S | Save |
| Ctrl+Shift+S | Save As |
| Ctrl+P | Print |
| Ctrl+F | Find |
| Ctrl+H | Find & Replace |
| Ctrl+Z / Ctrl+Y | Undo / Redo |
| Ctrl+, | Preferences |
| F1 | Keyboard shortcuts help |
| F6 / Shift+F6 | Cycle / reverse-cycle UI regions |
| F11 | Full screen |
| Alt+Left / Alt+Right | Navigate back / forward |
| Ctrl+0 | Actual size |
| Ctrl++ / Ctrl+- | Zoom in / out |
Architecture
GlyphPDF v1.5.0 is publicly released (Apache-2.0). The architecture integrates three workstreams committed per ROADMAP.md:
- Dual-Model Core — Structural model (PDF object graph owned by PoDoFo + PDFium + qpdf — source of truth for sign/redact/forms/exact layout) ↔ Semantic model (
docmodel::SemanticDocument — editing/interchange model). LuaDjotCodec encodes a SemanticDocument to Djot and decodes Djot back into a SemanticDocument by walking the vendored reference parser's AST. The round-trip is structure-preserving for the document's section tree — section nesting, titles, paragraph/list text, and inline emphasis/strong/code round-trip exactly (verified by TestDjotRoundtrip::testStructuralRoundtrip and per-seed section-count equality in TestDjotFuzz). It is not yet a byte-exact round-trip for every block construct: standalone heading blocks are promoted to sections on reparse and empty code blocks are dropped, so top-level block counts are not guaranteed to match (the decode never invents content — decoded block count ≤ original). Semantic ↔ PDF is EXPLICITLY LOSSY both ways and is gated: applySemanticToPdf requires a ProvenanceToken that only ProvenanceGuard::mintApplyToken can mint (compile-time chokepoint), and the guard refuses Djot-edit-save-back for signed documents.
- Heterogeneous LaneScheduler — GPU lane (warm persistent worker, never spawn-per-page) + CPU lane (QtConcurrent, core-count) + cross-page pipelining (
layout(P+1) ‖ ocr(P) ‖ fusion(P-1)). Reused by: OCR ensemble, MRC compression pipeline, future GPU workloads.
- Parallel Layout + OCR Ensemble (WS1) — PP-DocLayoutV2 layout detector (+ Surya when license permits) with IoU reconciliation → per-region Tesseract + RapidOCR PP-OCRv5 fanout via LaneScheduler → word-level confidence-weighted ROVER fusion. Per-region redo + per-word confidence overlay in OCRMode.
- Djot Full Document Interchange (WS2) —
docmodel + pdfws_djot libraries; vendored Lua 5.4 reference parser (MIT); three roles: (a) OCR output mapping to SemanticDocument, (b) authoring input (Djot → Semantic → PoDoFo content stream), (c) annotation/comment rich text (Djot internal model, transcoded to /RC XHTML + /Contents plain text on save, original stashed in /PieceInfo for perfect GlyphPDF round-trip with Acrobat/Foxit interop).
- MRC Layered Compression in PDF/A (WS3) ✅ — Layout-region-guided mask separation (
MrcPageProcessor) → JBIG2 lossless foreground (jbig2enc Apache-2.0; NEVER pattern-matching per 2013 Xerox incident) + JPEG2000 background (OpenJPEG 2.5.4 BSD-2, already in MSYS2) + invisible 3 Tr OCR sandwich text from WS1 word boxes → PDF/A-2b assembly with XMP metadata + sRGB OutputIntent → veraPDF subprocess validation gate. Achieved: 30.4× compression (86 KB vs 2.64 MB raw pixels on A4 test page). Off/Lossless/Balanced/Aggressive modes in CompressDialog. Optional DjVu importer (HAS_DJVU=OFF default; import-only, no DjVu output).
┌────────────────────────────────────────────────┐
│ Application Layer (GpMainWindow + Ribbon) │
└──────────────────────┬─────────────────────────┘
│
┌──────────────────────▼─────────────────────────┐
│ Dual-Model Core │
│ Structural (PDF object graph) │ Semantic │
│ PoDoFo / PDFium / qpdf │ docmodel │
│ ProvenanceGuard ◄── boundary ──► pdfws_djot │
└──────────────────────┬─────────────────────────┘
│
┌──────────────────────▼─────────────────────────┐
│ Heterogeneous LaneScheduler │
│ GPU lane (warm worker) │ CPU lane (pool) │
│ Cross-page pipeline: layout ‖ ocr ‖ fusion │
└──────────────────────┬─────────────────────────┘
│
┌──────────────────────▼─────────────────────────┐
│ OCR Ensemble (WS1) │ MRC Pipeline (WS3) │
│ Layout+OCR fanout │ JBIG2 + JP2K + Sandwich│
└────────────────────────────────────────────────┘
FORBIDDEN: MuPDF (AGPL-3.0), Poppler (GPL-2.0+), DjVu output, veraPDF in-process linking.
License
GlyphPDF is open source under Apache-2.0.
Architectural constraints (per ROADMAP "Forbidden Dependencies"):
- MuPDF (AGPL-3.0): Never linked in-process — CMake FATAL_ERROR guard enforces.
- Poppler (GPL-2.0+): Never linked in-process — CMake FATAL_ERROR guard enforces.
- DjVu: Excluded as output format (legacy; minimally maintained). Optional importer only for legacy corpus ingestion.
- veraPDF (AGPL-3.0): Subprocess only, never linked in-process (used for PDF/A conformance validation).
All third-party dependencies are documented in LICENSE-3RD-PARTY.md.