Why Edited PDF Text Shows Empty Boxes
The text layer says one thing. The page shows another. This is the most common way a PDF text editor corrupts a document without anyone noticing.
The symptom
You change Policy ABC to Policy QWXZ in a PDF. You open the result.
Policy â–¡â–¡â–¡â–¡
Four empty boxes. You select the text and copy it. Your clipboard says Policy QWXZ.
The letters are there. They just have no shape.
Why it happens
A PDF does not embed a font. It embeds a font subset: only the glyphs the document
actually uses. If the original never contained a Q, the embedded font has no drawing
for Q.
When you type a Q into that font, the PDF viewer looks up the glyph, finds nothing,
and draws the font's .notdef character. Usually a box. Sometimes nothing.
But the text is still a Q. The content stream says so. Text extraction says
so. Search finds it. Only the pixels are wrong.
| Layer | What it contains |
|---|---|
| Content stream | Policy QWXZ |
| Text extraction / copy | Policy QWXZ |
| Rendered page | Policy â–¡â–¡â–¡â–¡ |
Why this bug ships
Because every check you would naturally write passes.
I wrote a PDF text editor. My tests replaced text, saved the file, ran
pdftotext on the output and compared. Green. The extracted text was correct. It always
would be — the bug is not in the text.
I found it by adding a synthetic document with a deliberately tiny subset font, then rendering the output to an image and looking. Then I found the same failure live, in a real form, that my engine had been reporting as a successful edit.
The wrong fixes
Embed a full font. You do not have one. The PDF has a subset. Fetching the real font by name from the system is a guess, and the guess is often wrong — and now the file is 400 KB heavier.
Draw the new text in a different font. Now one word on the line looks different. And if the original font was subset, this one probably is too.
Cover the old text with a white box and draw new text on top. This is what most "free PDF editors" do. The old text is still in the file. It breaks on coloured backgrounds. It is not editing; it is a sticker.
The right fix: refuse
Before writing an edit, read the embedded font's character map. TrueType stores it in the
cmap table — formats 0, 4, 6 and 12 cover what PDFs embed. Build the set of characters
the font can draw. Check every character of the new text against it.
If one is missing, do not write. Say which:
Cannot write "Policy QWXZ": this font has no glyphs for Q, W, X, Z
The user now knows exactly what happened and can choose different words. A refused edit costs ten seconds. A document that looks broken to the reader and correct to the writer costs a lot more, and is discovered a lot later.
A rule that generalises
Across every format that separates meaning from appearance — PDF, SVG, rich text, HTML with web fonts — the same failure exists. The data is right. The rendering is wrong. Your tests check the data.
The only reliable checks are: render it and look, or verify against the appearance layer directly. For PDF that means parsing the font, not trusting the text.
Two other cases in the same family, for completeness:
- CID / Type0 fonts use multi-byte codes. A naive editor writes single-byte codes into them and produces garbage. Detect, and refuse.
- Form XObjects hold text outside the page stream. A naive editor never sees it. Report it as not editable rather than pretending it is not there.
Knowing when to refuse turned out to be most of the work. The editing was the easy part.
RetypePDF edits the text inside a PDF in your browser. Nothing is uploaded. No account, no price.
Try it