Engineering Journal
Pdf Processor
Pdf Processor

Column boundaries are rendering artifacts: reconstructing text flow from spatial fragments

2026-07-04

TLDR

Concatenating multi-column text fragments mid-sentence permanently destroys spatial rendering fidelity. Preserving document structure requires an explicit linking pattern (data-flow-next, data-flow-prev) evaluated by a multi-signal classification stack. Evaluating terminal punctuation alone fails on headings and missing table borders; combining last-line full-width ratios, first-line indent checks, and font continuity guarantees precise paragraph continuation linking.
Classification SignalSignal Evaluation RuleCorroboration Value
Terminal Punctuation!endsWithTerminalPunct(line)Weak alone (Triggers false-positives on headings)
Last-Line Full WidthlastLine.width >= colWidth * 0.95Strong (Unfinished paragraphs span full width)
First-Line Indent!nextFirstLine.hasIndentStrong (Continuations start flush to margin)
Font ContinuityfamilyMatch && Math.abs(sizeA - sizeB) < 0.5Strong (Filters out footnote transitions)

Technical multi-signal continuation classifier

// Multi-Signal Continuation Classifier with Hard Vetoes
export function shouldLinkParagraphContinuations(prevFragment, nextFragment, colWidthPx) {
  // Hard Vetoes: List markers, digit-heavy tables, or TitleCase headings
  if (/^\s*[\bullet\d+[\.\)]]/.test(nextFragment.firstLineText)) return null;
  if (isDigitHeavy(prevFragment) || isDigitHeavy(nextFragment)) return null;

const prevLastLine = prevFragment.lines.at(-1); const nextFirstLine = nextFragment.lines[0];

// Self-Announcing Hyphen Signal if (endsWithHyphen(prevLastLine.text)) { const isLowercase = /^[a-z]/.test(nextFirstLine.text); return { shouldLink: true, joinMode: isLowercase ? 'dehyphenate' : 'hyphen-keep' }; }

// Multi-Signal Corroboration Stack const isFullWidth = prevLastLine.widthPx >= colWidthPx * 0.95; const isFlushLeft = !nextFirstLine.hasIndent; const fontMatches = prevLastLine.fontFamily === nextFirstLine.fontFamily && Math.abs(prevLastLine.fontSizePt - nextFirstLine.fontSizePt) < 0.5;

if (!endsWithTerminalPunct(prevLastLine.text) && (isFullWidth || (isFlushLeft && fontMatches))) { return { shouldLink: true, joinMode: 'space' }; }

return null; }

<!-- Spatial HTML Output with Flow Relationship Attributes -->
<div id="p3-f0" class="pdf-region" data-flow-next="p3-f1">The day is</div>
<div id="p3-f1" class="pdf-region" data-flow-prev="p3-f0" data-continuation="true" data-flow-join="space">brighter than yesterday.</div>
Rule of thumb: Link multi-column text fragments via HTML data attributes rather than executing destructive string concatenation, using last-line width and font metrics as continuation signals.
Read this post in the full Engineering Journal →