Skip to content

fix(docx): set a panel's layer where its alignment sets it - #924

Merged
DemchaAV merged 1 commit into
2.5-devfrom
fix/docx-layer-align-in-cell
Oct 19, 2026
Merged

DemchaAV merged 1 commit into
2.5-devfrom
fix/docx-layer-align-in-cell

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Why

A filled or outlined rectangle or rounded rectangle with text, composed in a table cell, is
written as a panel: a table of one cell (writtenAsAPanel → writePanel). Its cell was always
written vAlign=center ("the page centres a shape's layers in it"), and its layers were written
from the cell's left, whatever their LayerAlign.

Measured in Word 16 and LibreOffice on Windows, in a 100×60pt panel in a table cell:

Layer Page Before, in Word / LibreOffice After, in Word / LibreOffice
a label at TOP_LEFT x 76, baseline 103.2 x 76, baseline 125.7 / 125.8 x 76, baseline 102.2 / 102.3
a label at BOTTOM_RIGHT x 242.3, baseline 150.2 x 196, baseline 125.7 / 125.8 x 242.4, baseline 149.2 / x 241.9, 149.3

Neither was named. The 1pt that is left over is Word's own: the paragraph above the table,
"Before", stands 0.9pt higher too.

What changed

  • verticalOfItsLayers: the panel's cell sets what it writes at the top, the middle or the
    foot, where its first written layer is set. Top is Word's default and is not written.
    • The chip-label logic (composedLabelOf and what follows) takes only a label centred top to
      bottom, so it still sees a centred cell.
  • holdInItsPanel: each written layer is held in across through holdIn, from the shape's
    room as written (its outline less the padding written as the cell's margins).
    • The box width is read off the lines its table laid out for it (firstTextBox), and set at the
      alignment's share, as the engine does (LayerStackGeometry.horizontalOffset), plus its offset.
    • A paragraph whose own alignment leans the way its layer's does, and that no offset moves, is
      left as it was. A centred or right-aligned paragraph is as wide as the shape.
    • writeChildren takes the shape and holds each child in turn, restoring the insets after it.
  • reportTheLayersOfItsPanel names (layer offset) what the cell cannot set where the page
    does:
    • a written layer after the first, which the cell writes under the layers before it, at their
      height or at another;
    • an offset down or up;
    • a box the page sets past the shape's right edge, where the cell's text ends (one left of it is
      named where holdIn holds it);
    • a layer set across by a box the layout does not give: one that is not a paragraph, or a
      paragraph whose lines are not found.
  • Composed content has no path of its own in the layout, so these notes carry none, as the other
    notes on composed content do.
  • Docs:
    • the recipe's composed-panel paragraph;
    • the capability matrix's layer-stack row;
    • the layers entry of DocxNodeFieldLedgerTest for the shape container;
    • CHANGELOG v2.5.0;
    • four comments that said a shape's layers are centred.

Verification

  • Corpus, 62 DOCX before and after: all 62 are byte-identical, and the report's 1246 notes are
    identical. A scan finds 123 shape containers composed in table cells:
    • 108 rectangles holding one paragraph at CENTER, all written exactly as before;
    • 15 more (ellipses, and icon tiles holding only drawing), which are not written as panels.
  • DocxPanelLayerAlignTest (new, 12 tests):
    • top, foot and middle cells;
    • a left paragraph held to its box at the right and in the middle, both sides;
    • a leaning paragraph not held in;
    • an offset across, and one left of the shape named;
    • an offset down named;
    • layers at different heights, and at one height, named;
    • a centred paragraph moved past the shape's edge named;
    • a padded shape held in its room;
    • a section set across named.
  • 12 sabotages, all caught:
    • the cell always centred;
    • layers not held in;
    • a leaning paragraph held in;
    • the share ignored;
    • the offset ignored;
    • later layers unnamed;
    • an offset down unnamed;
    • a box not given unnamed;
    • the panel not reported;
    • the box too wide;
    • past the right edge unnamed;
    • the room without the padding.
  • ./mvnw -B -ntp clean verify: BUILD SUCCESS (core 821, render-docx 1831, examples 93, qa 1820).
    The knowledge pack's --check passes.

The page sets a shape container's padding outside its outline, and its layers in the outline. The
panel writes the padding inside the outline, as the cell's margins. With padding, what the panel
writes therefore stands that far inside the outline, at either side. This is unchanged here.

Lane: render-docx (semantic backend). DOCX output changes only for a shape written as a panel
in a table cell whose written layer is set at its top or foot, or whose paragraph stands across
where its own alignment does not set it.

A filled or outlined rectangle with text, composed in a table cell, is
written as a panel, a table of one cell. Its cell was always centred and
its layers written from the cell's left. Measured in Word and
LibreOffice, a label at the top-left of a 100x60 panel stood 22.5pt low,
and one at the bottom-right stood in the middle at the left.

The cell now sets what it writes at the top, the middle or the foot, as
its first written layer is set, and each paragraph layer is held in
across to its box, its width read off the lines its table laid out for
it, set at its alignment's share and moved by its offset.

What the cell cannot set is named (layer offset): a layer after the
first, which it writes under the ones before it; an offset down or up;
a box past the shape's side; and a layer set across by a box the layout
does not give.
@DemchaAV
DemchaAV merged commit 6071ea4 into 2.5-dev Oct 19, 2026
13 checks passed
@DemchaAV
DemchaAV deleted the fix/docx-layer-align-in-cell branch October 19, 2026 17:15
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