Skip to content

Read a free text box's border width from /Border when it has no /BS - #118

Merged
bobsingor merged 3 commits into
embedpdf:embedpdf/mainfrom
KleiKodesh:fix/free-text-plain-box
Nov 15, 2026
Merged

bobsingor merged 3 commits into
embedpdf:embedpdf/mainfrom
KleiKodesh:fix/free-text-plain-box

Conversation

@KleiKodesh

@KleiKodesh KleiKodesh commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

A free text box without /BS always got the default 1 pt border, even when its /Border array gives another width. Under ISO 32000-1 12.5.2, an annotation with no /BS takes its border from /Border (default [0 0 1]). So a box with /Border [0 0 0] and no appearance stream drew a 1 pt frame and inset its text by 2 pt on every side, and text in a tightly sized box wrapped and was clipped.

The plain box was the only free text border reader that skipped /Border. The callout, the shape generators and EPDFAnnot_GetBorderStyle already take its width when there is no /BS. The viewer therefore read width 0 (no frame, text at the box edge) while the drawn appearance had a frame and an inset.

Change

  • Without /BS, a plain free text box's border width comes from /Border, as the callout reads it. With neither key, the border stays at the ISO default of 1 pt. /BS still wins when both are present.
  • A width of 0 draws no frame, and the text plate is the whole box (FreeTextPlate, twice the border width).

Layout is unchanged: a borderless box wraps its text in the box like any other box. An earlier version of this PR also changed how plain borderless boxes lay out (no wrapping, shrink to fit, direction from the text). That part was dropped: it chose a layout from the border width, so every borderless plain box would stop wrapping.

Tests

  • New unit test CPDFGenerateAPTest.FreeTextBorderWidthFromBorderArray: /Border [0 0 0] draws no frame with the plate equal to the box, and draws the same stream as /BS << /W 0 >>; /Border [0 0 3] draws as /BS << /W 3 >>; neither key draws as /BS << /W 1 >> (framed, plate inset 2 pt); /BS wins over /Border.
  • macOS arm64: unit suite 1360 passed (base 1359 plus the new test); embedder suite 1795 tests with the same 12 failures as an unchanged build of the base (Mac golden and progressive-render failures).
  • No pixel or embedder fixture has a free text box with a /Border array, so no golden changes.

KleiKodesh and others added 2 commits November 10, 2026 08:31
A free text box without /BS took the default 1 pt border even when its
/Border array says 0, so a box PDF.js wrote (/Border [0 0 0], no /AP,
no /RC) got a frame and a text plate inset by 2 pt on every side. Its
rect fits the text as PDF.js measured it, so the text then wrapped and
the second line was clipped away.

- Without /BS, the box's border width is the /Border array's, as the
  callout already reads it.
- A plain box (no /RC) whose border is 0 lays out as PDF.js draws it:
  lines break only at line breaks, text too wide or too tall for the
  box is drawn smaller to fit (CPDF_RichTextLayout::Options::
  shrink_to_fit), and each paragraph reads in its text's direction.
A borderless plain box lays out like every other box: its lines wrap
in the box. Choosing a layout from the border width would stop every
borderless plain box from wrapping, whoever wrote it.

The test now checks the width rule: /Border draws as the same width in
/BS does, frame and text plate alike; 1 pt with neither; /BS first.
@bobsingor bobsingor changed the title Draw a plain borderless free text box as PDF.js does Read a free text box's border width from /Border when it has no /BS Nov 15, 2026
@bobsingor
bobsingor merged commit 53e18bb into embedpdf:embedpdf/main Nov 15, 2026
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.

2 participants