mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-14 19:27:04 -04:00
* M10: edit OCR text on scanned pages so the change shows Editing a recognised word on a scan rewrote it as invisible OCR text, so the page still showed the old word, and the whole OCR layer grouped into one paragraph that rewrapped when one word changed. - An edited invisible paragraph is drawn visibly, over a cover in the paper colour sampled around it, in the scan's sampled ink colour (or the chosen colour). - OCR words group into phrases: a table cell or a tab stop splits them and each scanned line stays apart; a phrase grows rightwards. - Styled rewrites measure with the text matrix's horizontal scale, so stretched OCR words keep their widths instead of overlapping. - The inline editor covers the scanned word and grows like the result. * M10: size OCR text from each word's letters A word box from recognition is tight around the ink, but the text layer assumed every box spans Helvetica's ascender-descender height. A capitals-only word such as "DT" spans only the cap height, so its text was set about 23% too small and its baseline floated up; editing it then drew the new word visibly smaller than the scanned one. The em and baseline now come from the word's letters: cap height or x-height on top, descender or baseline at the bottom. On a real scanned form, a rewritten "DT" -> "DSI" now matches the scanned word's height and baseline. The engine OCR-edit tests build their words the way a scan would box them. * Edit OCR text: sample colours only for invisible blocks, from the current bytes Session::apply looked up every edited block with a fresh text_blocks pass and re-serialized the whole document to render the sampling tile. Text blocks are now cached per page on the editor (keyed on the unmodified document's source identity, so any edit, undo or save invalidates them), visible blocks skip sampling entirely, and the tile renders from the document's current bytes. Adds a visible stretched-text regression test and documents that editing any invisible text makes it visible over a painted cover. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Edit OCR text: name the cached text-blocks tuple (clippy), rustfmt Co-Authored-By: Claude Opus 5.5 <[email protected]> --------- Co-authored-by: Brandon Thomas <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]>
68 lines
5.0 KiB
Markdown
68 lines
5.0 KiB
Markdown
# Editing existing text and source subsets
|
|
|
|
Click a text region in **Edit a PDF → Edit text and images**. One editor contains its
|
|
source rows and mixed styles. Embedded TrueType and OpenType/CFF faces are used in memory;
|
|
source font programs, colour, size and baseline anchors stay intact. A textless preview
|
|
prevents a second copy underneath. The frame shows the live extent as text grows or shrinks.
|
|
|
|
A subset font contains only some of the original face's glyphs. A new character cannot be
|
|
reconstructed from a glyph the PDF does not contain. **Load font…** imports an openly licensed,
|
|
embeddable standalone `.ttf` or `.otf` face. **Installed fonts…** discovers eligible user-installed
|
|
faces on request, off the UI thread; the document-font menu selects resources already on the
|
|
page. Select **Keep source fonts** to preserve each run's original face. A matching full face
|
|
completes its subsets automatically, including new Chinese characters. Choosing another face
|
|
is explicit. Fonts with restricted embedding, unsupported collections, excluded families or
|
|
no open-licence declaration are refused. Interface fallback fonts are never exported.
|
|
|
|
The full selected program, glyph mappings, widths and Unicode text are embedded in the PDF.
|
|
Saving and reopening therefore needs no locally installed font. Original subset bytes are
|
|
preserved. Optional matching faces from `CRAFT_FONTS_DIR` can also complete source subsets;
|
|
this works only when that build input actually contains the full face. This change does not
|
|
add a font binary or change the release font pin. Fonts shared by releases belong in
|
|
`storytold/craft-fonts` under the repository's asset rules.
|
|
|
|
Select text within the editor before changing size, colour, font, underline or spacing to
|
|
format that selection. Automation supports up to 1024 disjoint UTF-8 byte ranges with the
|
|
same properties; invalid or overlapping ranges fail atomically. Untouched source formatting
|
|
survives. OpenType shaping uses the selected/source face's substitution and positioning
|
|
rules, preserves marks and ligatures, and applies Unicode bidi ordering for a single face.
|
|
Logical text remains available after save/reopen through ToUnicode and ActualText.
|
|
Added Arabic text records ActualText per shaped line for copying and searching in typing order.
|
|
ActualText already supplies typing order, so the editor preserves it without applying
|
|
a second bidi reversal; adjacent visual glyph runs still recover their own reading order.
|
|
Only right-to-left ActualText is kept apart this way: left-to-right spans, such as the Latin
|
|
ligatures (`fi`, `fl`) Word and Chrome wrap in ActualText mid-word, join their line as before.
|
|
|
|
For headless editing, use `text_font_files` → `text_font_import` → `text_fonts` and pass a
|
|
resource to `text_edit.font_resource`. `text_edit.ranges` holds selected range formatting.
|
|
`text_edit_layout` accepts resource/ranges too and measures a draft without applying it.
|
|
All file inputs respect CLI root confinement; importing a font and applying text are undoable.
|
|
|
|
On a scanned page, recognised text (Scan & OCR) is an invisible layer over the picture. Edit
|
|
text groups it into phrases: words joined by a word space, with a table cell, a tab stop and each
|
|
scanned line kept apart. Applying an edit draws the new text visibly in the scan's ink colour (or
|
|
the one chosen) and first covers the old words with the paper colour sampled around them. Each
|
|
word keeps its position and width, and a longer phrase grows rightwards rather than wrapping. The
|
|
cover is one flat colour, and the text uses the layer's Helvetica, not the scanned typeface.
|
|
This applies to any invisible text (rendering mode 3), not just a PdfCraft OCR layer: editing
|
|
invisible text, such as another OCR tool's layer, makes the rewritten paragraph visible over a
|
|
painted cover in the sampled paper colour. Edit text also groups invisible text differently: its lines never
|
|
merge into multi-line paragraphs, and words split at gaps of 0.6 em or more.
|
|
|
|
Explicit marked paragraph/heading scopes prevent unrelated tagged regions from merging.
|
|
Compatible geometry groups untagged content, including runs split across content streams
|
|
or equivalent graphics transforms. Geometry cannot infer author intent in every untagged
|
|
PDF. Semantic structure-tree preservation, legacy Type 1/Type 3 inline font preview,
|
|
font collections/variable-font instances, mixed-font/style contextual runs and complete rotated
|
|
layout fidelity still need broader coverage. Do not interpret the passing real-file checks
|
|
as a guarantee for every PDF.
|
|
|
|
Private acceptance tests are opt-in and keep inputs unmodified. They exercise actual Chinese
|
|
keyboard insertion/deletion on all four pages, source-face/baseline checks and identical
|
|
in-memory renders before and after saving/reopening. Synthetic tests cover full TrueType
|
|
mapping, OpenType/CFF, Arabic marks/ligatures/mixed bidi, repeated edits, disjoint styles,
|
|
invalid ranges, font selection and root confinement. CLI acceptance repeats insertion/deletion
|
|
and two saves/reopens on four pages; independent PDFium checks extraction and rendering.
|
|
No private document, font or screenshot
|
|
is included in the repository.
|