Skip to content

fix(render-pdf): draw text decoration marks and honour alpha on text, lines, and table paint#418

Merged
DemchaAV merged 2 commits into
developfrom
fix/pdf-decorations-alpha
Jul 19, 2026
Merged

fix(render-pdf): draw text decoration marks and honour alpha on text, lines, and table paint#418
DemchaAV merged 2 commits into
developfrom
fix/pdf-decorations-alpha

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Why

A cross-backend parity audit found the reference PDF backend silently losing two documented style capabilities the PPTX backend already delivers. DocumentTextDecoration.UNDERLINE/STRIKETHROUGH resolved only to font faces that alias to the regular program, so decorated text rendered as plain glyphs. And DocumentColor.rgba's alpha channel was honoured only on shape fills and strokes — text runs, lines, side borders, and table paint rendered fully opaque, so a translucent style produced different output per backend.

What

  • PdfTextDecorations draws underline and strikethrough as em-proportional filled bands in the run's colour — underline 0.10 em below the baseline with 0.05 em thickness (the Type 1/Helvetica-AFM convention), strikethrough 0.28 em above. Marks are collected while the glyphs stream out (path fills are illegal inside BT/ET) and painted after the text, on paragraph runs, chips (only when the chip actually painted glyphs), and table cell text (measured with the same sanitized string the cell draws).
  • Alpha lands on every remaining surface through PdfAlphaSupport: line fragments, per-side shape borders, and table cell fills, borders, and text use the translucent-only applyFillAlpha/applyStrokeAlpha, while the paragraph run-state tracker routes its emissions through a shared setFillAlpha helper — it must also write an explicit opaque constant, because a gs survives ET and nested draws (chips, inline graphics, decoration marks) would otherwise inherit the translucent state. Each alpha change mints a fresh ExtGState resource; deduplicating them per render pass is tracked in Dedupe ExtGState alpha resources per render pass #419.
  • Fully opaque, undecorated documents render byte-identically to before: every new operator is gated on a translucent colour or a decorated run.
  • Docs: the capability matrix's alpha row is now ✅ for both fixed-layout backends, the text-decorations row records the PDF marks (and that PowerPoint draws its own, with sub-point placement differences), and DocumentColor.rgba's Javadoc drops the opaque-surfaces caveat.

Verification

  • PdfDecorationAndAlphaRenderTest (12 raster-comparison tests): the underline extends ink strictly below descender-free glyphs (catches a flipped offset), the strikethrough stays inside the glyph band (bounded above and below), translucent text, lines, table fills, table borders, table cell text, and side borders each render measurably lighter than their opaque twins, an underlined chip and an underlined table cell add mark ink, an opaque run's underline stays fully dark when a translucent run follows it on the same line, and an opaque inline shape after a translucent run stays fully dark — the two tests that pin the reset-before-nested-draw rule.
  • Full reactor gate green: clean verify across core, render-pdf, render-docx, render-pptx, templates, testing, root, bundle, qa, coverage — including the qa visual-regression suites, which confirm no shipped template's pixels moved.

@DemchaAV
DemchaAV merged commit 473665b into develop Jul 19, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the fix/pdf-decorations-alpha branch July 19, 2026 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant