GlyphPDF is a comprehensive open-source PDF workstation designed for editing, annotating, signing, redacting, OCRing, and compressing PDF documents offline. Built with privacy in mind, it operates without any telemetry or cloud dependencies.
Key Features:
Inline Text Editing: Modify text directly within PDFs.
Security & Signatures: AES-256 encryption, PAdES digital signatures for B-LT/B-LTA compliance.
Offline OCR: Utilizes multiple engines (ROVER ensemble) for accurate text recognition without internet access.
Audience & Benefit:
Ideal for professionals in legal, finance, or government sectors who prioritize data security and efficiency. GlyphPDF offers secure PDF management with precise control over documents, ensuring privacy and meeting compliance requirements.
Install via winget for a seamless experience, designed to meet the needs of users seeking reliable, offline document solutions.
README
GlyphPDF v1.3.1 — 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.
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 v1.0 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).
> 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.
> 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.
Build (Windows + MSYS2)
Open the MSYS2 UCRT64 shell (C:\msys64\ucrt64.exe) or any shell with C:\msys64\ucrt64\bin on PATH:
cd /c/Users/User/Projects/pdf
mkdir -p build && cd build
cmake .. -G "Ninja"
cmake --build . --parallel 8
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.
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).
Testing
set QT_QPA_PLATFORM=offscreen
cd build
ctest --output-on-failure
14 test targets:
Target
Category
What it tests
UnitTests
Unit
Core utility validation
TestInterfaces
Unit
Engine API contracts
SmokeTest
Integration
End-to-end load/save/modify
TestSanitization
Security
Metadata stripping vectors
TestSignatureValidation
Security
Byte-range and trust validation
TestRedaction
Security
Content stream excision, XObject redaction
TestThreadSafety
Concurrency
Mutex validation under concurrent access
TestEncryption
Security
AES-256 generation and enforcement
TestResourceLimits
Resilience
Page/buffer size boundaries
TestControllers
UI
Controller action dispatch
TestIntegration
E2E
Full workflow: open, edit, save, encrypt, rotate, redact
TestPerformance
Benchmark
Open/save timing, metadata ops, error overhead
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.3.1 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).