feat: rebrand to MMD PDF, single corporate theme, and remove original text under an edit
- Services/PdfRedactText.cs: strip text whose origin falls inside a CoverAnnotation from the page content stream at save time, hooked into PdfBurn.DrawAnnotationsIntoDoc. Fixes edited values staying recoverable by text extraction. - Themes/MMD.xaml replaces all thirteen themes; picker and accent strip removed; no dark mode. - Rename KillerPDF -> MMD PDF across code, resources, packaging and locale strings; new icon. - Remove the upstream author credit and the in-app install button.
This commit is contained in:
+15
-15
@@ -1,19 +1,19 @@
|
||||
# Standards-conformance validation results - KillerPDF 1.7.5
|
||||
# Standards-conformance validation results - MmdPdf 1.7.5
|
||||
|
||||
veraPDF run date: 2026-08-22, against the 1.7.5 release build. This small maintenance release
|
||||
changes live annotation rotation behavior, mouse-wheel navigation, shortcuts, and localization,
|
||||
without changing the PDF serializer. The standard open/save pipeline was nevertheless run fresh
|
||||
across the complete corpus because every KillerPDF release must independently meet the same
|
||||
across the complete corpus because every MmdPdf release must independently meet the same
|
||||
zero-regression bar. The run reproduces every established count exactly: 2,236 successful resaves, 671 refusals
|
||||
matching the SKIP rows one for one, 63 improvements, and the same single documented PDF/A-4
|
||||
header case as the only flagged saved file. The qpdf sweep also reproduces its table exactly:
|
||||
2,032 clean both sides, 195 improved, 9 kept preexisting warnings, 0 worsened.
|
||||
|
||||
Question under test: does saving a PDF through KillerPDF degrade its
|
||||
Question under test: does saving a PDF through MmdPdf degrade its
|
||||
standards conformance? Every file in a 2,907-file public corpus was validated, resaved through
|
||||
KillerPDF's standard open/save pipeline, and validated again.
|
||||
MmdPdf's standard open/save pipeline, and validated again.
|
||||
|
||||
Result: **Zero** conformance regressions across every file KillerPDF will save, with one documented engine limitation
|
||||
Result: **Zero** conformance regressions across every file MmdPdf will save, with one documented engine limitation
|
||||
(PDF/A-4's PDF 2.0 header). **63 files came out more conformant than they went in.**
|
||||
|
||||
## Tools
|
||||
@@ -22,7 +22,7 @@ Result: **Zero** conformance regressions across every file KillerPDF will save,
|
||||
|---|---|---|
|
||||
| veraPDF | 1.30.2 | PDF/A + PDF/UA validation (the industry reference validator) |
|
||||
| qpdf | 12.3.2 | Structural check (`--check` exit codes) |
|
||||
| KillerPDF | 1.7.5 | `--batch-resave` through the standard open/save pipeline |
|
||||
| MmdPdf | 1.7.5 | `--batch-resave` through the standard open/save pipeline |
|
||||
| Compare-VeraPDF.ps1 | this folder | Diffs the two veraPDF reports file by file |
|
||||
| QpdfSweep.ps1 | this folder | Structural before/after sweep (`qpdf --check` exit codes) |
|
||||
|
||||
@@ -36,7 +36,7 @@ standard, so any structural damage a resave introduces shows up as a new failed
|
||||
## Method
|
||||
|
||||
1. Validate the pristine corpus: `verapdf --recurse --format json <corpus> > baseline.json`
|
||||
2. Resave every file through KillerPDF: `KillerPDF.exe --batch-resave <corpus> <resaved> --log resave.csv`
|
||||
2. Resave every file through MmdPdf: `MmdPdf.exe --batch-resave <corpus> <resaved> --log resave.csv`
|
||||
3. Validate the resaved tree the same way into `after.json`
|
||||
4. `Compare-VeraPDF.ps1` matches files by relative path and flags any file that fails a rule
|
||||
after the resave that it did not fail before
|
||||
@@ -56,7 +56,7 @@ standard, so any structural damage a resave introduces shows up as a new failed
|
||||
| Improved (fails fewer rules than before) | 4 |
|
||||
| Regressed | 1 (the documented PDF/A-4 header case below) |
|
||||
|
||||
The 671 skips are encrypted files and files damaged beyond parsing. KillerPDF refuses to
|
||||
The 671 skips are encrypted files and files damaged beyond parsing. MmdPdf refuses to
|
||||
resave what it cannot fully read rather than risk writing a damaged file; each one is a SKIP
|
||||
row in `resave.csv`, and all 671 files absent from the after-report cross-check exactly
|
||||
against those SKIP rows. No file went missing for any other reason.
|
||||
@@ -67,10 +67,10 @@ through a clean serializer repairs that class of defect.
|
||||
|
||||
## The one known limitation: PDF/A-4
|
||||
|
||||
ISO 19005-4 (PDF/A-4) is built on PDF 2.0 and requires a `%PDF-2.0` header. KillerPDF's write
|
||||
ISO 19005-4 (PDF/A-4) is built on PDF 2.0 and requires a `%PDF-2.0` header. MmdPdf's write
|
||||
engine serializes PDF 1.7, so the single PDF/A-4 corpus file gains ISO 19005-4:2020 clause
|
||||
6.1.3 tests 4 and 5 after a resave. This is a version-marker limitation, not structural
|
||||
damage: qpdf reports the resaved file clean. PDF 2.0 serialization is future work; KillerPDF
|
||||
damage: qpdf reports the resaved file clean. PDF 2.0 serialization is future work; MmdPdf
|
||||
does not claim PDF/A-4 output.
|
||||
|
||||
## qpdf structural sweep
|
||||
@@ -89,7 +89,7 @@ No file's structural health got worse; 195 files with qpdf warnings came out cle
|
||||
## What had to be fixed to get here
|
||||
|
||||
The write engine is PdfSharpCore 1.3.67 (MIT), vendored under `third_party/PdfSharpCore/`
|
||||
with six patches, each marked `KillerPDF patch` in the source:
|
||||
with six patches, each marked `MmdPdf patch` in the source:
|
||||
|
||||
1. **No Producer/Creator stamping** into an imported document's Info dictionary. PDF/A
|
||||
(ISO 19005-1 clause 6.7.3) requires the Info dictionary to stay equivalent to the XMP
|
||||
@@ -106,7 +106,7 @@ with six patches, each marked `KillerPDF patch` in the source:
|
||||
leaked into indirect boolean objects as `True`, which is not a valid PDF token
|
||||
(ISO 32000-1 clause 7.3.2). This broke `/MarkInfo /Marked` in PDF/UA files.
|
||||
|
||||
On top of the library patches, every save runs three scrubs in KillerPDF itself:
|
||||
On top of the library patches, every save runs three scrubs in MmdPdf itself:
|
||||
|
||||
- **Dangling /Outlines removal** - reading `doc.Outlines` plants an empty outline dictionary
|
||||
that becomes a dangling reference (the 1.6.3 corruption bug).
|
||||
@@ -124,7 +124,7 @@ corpora). On a tree containing the corpus:
|
||||
|
||||
```
|
||||
verapdf --recurse --format json C:\pdf-corpus > baseline.json
|
||||
Start-Process -Wait KillerPDF.exe -ArgumentList '--batch-resave','C:\pdf-corpus','C:\pdf-corpus-resaved','--log','resave.csv'
|
||||
Start-Process -Wait MmdPdf.exe -ArgumentList '--batch-resave','C:\pdf-corpus','C:\pdf-corpus-resaved','--log','resave.csv'
|
||||
verapdf --recurse --format json C:\pdf-corpus-resaved > after.json
|
||||
.\Compare-VeraPDF.ps1 -Baseline baseline.json -After after.json `
|
||||
-BaselineRoot C:\pdf-corpus -AfterRoot C:\pdf-corpus-resaved -CsvOut compare.csv
|
||||
@@ -132,13 +132,13 @@ verapdf --recurse --format json C:\pdf-corpus-resaved > after.json
|
||||
-ResaveLog resave.csv -CsvOut qpdf-results.csv
|
||||
```
|
||||
|
||||
**The resave step must be `Start-Process -Wait`** (or otherwise blocked on): KillerPDF.exe is
|
||||
**The resave step must be `Start-Process -Wait`** (or otherwise blocked on): MmdPdf.exe is
|
||||
a GUI-subsystem binary, so a bare invocation returns immediately and the after-scan then
|
||||
validates a half-written tree - every not-yet-written file shows up as MISSING_AFTER (this
|
||||
burned the 1.7.0 run, twice).
|
||||
|
||||
The compare script counts every MISSING_AFTER as a regression by design, so a run with skips
|
||||
exits 1 even when clean. The release bar is: every MISSING_AFTER row cross-checks against a
|
||||
SKIP row in `resave.csv` (encrypted/unparseable files KillerPDF refuses to touch), and the
|
||||
SKIP row in `resave.csv` (encrypted/unparseable files MmdPdf refuses to touch), and the
|
||||
only rule-level change is the documented PDF/A-4 header case. Anything beyond that is a real
|
||||
regression.
|
||||
|
||||
Reference in New Issue
Block a user