Engineering Journal
Pdf Processor
Pdf Processor

Under the Hood: Rebuilding a Stacked Fraction the Text Layer Never Gave You

2026-07-19

TLDR

PDF text streams break display math equations into disjointed text items across multiple baseline offsets, omitting fraction bars entirely (which exist as vector lines in operator lists). Porting PDFium C++ math heuristics to JavaScript run-granularity uses a single core metric: comparing each atom's vertical offset ($\Delta Y$) against the local math axis scaled by body font size.
Atom Typographic PositionVertical Offset Threshold ($\Delta Y$)Structural Math Output
Numerator Territory$\Delta Y > +0.34 \times \text{fontSize}$\frac{numerator}{...}
Denominator Territory$\Delta Y < -0.30 \times \text{fontSize}$\frac{...}{denominator}
Sub / Superscript$\Delta Y

Technical math reconstruction engine

// Evaluate relative atom Y-offset from dominant local math axis
export function classifyMathAtomOffset(atom, localMathAxisY, baseFontSizePt) {
  const dy = atom.yCenter - localMathAxisY;

if (dy > 0.34 * baseFontSizePt) { return 'NUMERATOR'; } else if (dy < -0.30 * baseFontSizePt) { return 'DENOMINATOR'; } else if (atom.fontSizePt < 0.85 * baseFontSizePt) { return dy > 0 ? 'SUPERSCRIPT' : 'SUBSCRIPT'; }

return 'ON_AXIS'; }

// Distinguish overlapping overset annotations from trailing scripts export function isOversetAnnotation(atom, baseOperand) { // Oversets overlap base operand's X-range; scripts start at/after right edge const overlapThreshold = baseOperand.xMin + 0.3 * (baseOperand.xMax - baseOperand.xMin); return atom.xMin < overlapThreshold; }

<!-- Formatted Math Paragraph Output -->
<p data-math=""><span class="pdf-math">$x \overset{\text{maps to}}{\rightarrow} y = f_n(x) = \left(1+\frac{1}{x^n}\right)^n$</span></p>
Rule of thumb: Reconstruct 2D math layout by evaluating atom Y-offsets relative to local math axes, separating stretch delimiters from base font size metrics.
Read this post in the full Engineering Journal →