Skip to content

feat(engines): table layout for the layout engine - #842

Merged
KnifeLemon merged 1 commit into
builtin-enginesfrom
engine/tables
Oct 30, 2026
Merged

KnifeLemon merged 1 commit into
builtin-enginesfrom
engine/tables

Conversation

@KnifeLemon

Copy link
Copy Markdown
Owner

What does this change?

Implements the Project 4 item "Layout engine: tables".

Stacked on #840 (page composer). The base is engine/page-composer; it moves to builtin-engines once #840 is merged.

Table layout (Typesetting/TableLayout.cs)

  • Grid
    • Cells take their column, or the next free one past cells spanning down from above.
    • They keep their row and column spans.
  • Column widths
    • The table's absolute widths, else its relative ones (columns without one share the rest), else equal shares.
    • Tables of other formats, such as a spreadsheet's columns, are scaled down to the text width when they are wider.
    • 한글's tables keep the widths 한글 gave them.
  • Cells
    • Padding: the cell's, else the table's, else 한글's default 1.8 × 0.5 mm.
    • Content is laid out at the column width less the padding, nested tables included.
    • Lines on 한글's stored layout take their stored place inside the cell.
    • Vertical alignment: top, middle or bottom.
  • Row heights
  • Drawing
    • Fills, then content, then borders: the cell's, else the table's, else a thin grid.
    • Line styles: solid, dashed, dotted, dash-dot and double, at their width.
    • Captions go under the table.
  • Pages (in PageComposer)
    • Rows bound by spanning cells move together.
    • A table that must not split (한글 나누지 않음) moves to the next page whole when it fits on one.
    • Others split between rows (한글 셀 단위로 나눔).
    • Where rows may split, a row splits inside its cells unless the row must not split. That is 한글 나눔, and sources that don't say (Word's default).
    • Header rows repeat on every page.
  • Headers and footers are stacked through the same code, so tables in them work too.

한글's placement of tables

These came from comparing against 한글's own PDF, exported through 한글 automation. The model gains three layout-only members on HTable; the writers ignore them.

  • OuterMargin (hp:outMargin): the space kept around the table.
  • VerticalOffset (hp:pos vertOffset): where a table placed at its paragraph sits below the paragraph's top. 한글 puts the paragraph's text right under the table, without its space before.
  • OpensParagraph: the table is the first thing in its paragraph. The text after it keeps the paragraph's stored lines, whose starts still map, because the table is no text in the model. The reader used to drop those starts as "split by a table".
  • A table sitting in a paragraph's line as a character, where the paragraph has no text before the table (only floating objects):
    • the model's empty part before the table takes no line;
    • the table takes that paragraph's stored place and line spacing.

Measured

Against 한글's own PDFs of the HWPX files attached to issues (not in the repository):

Document Lines Pages Baselines
행정정보동의서 (#49) 82% → 100% 1/1 every line within 0.8 pt of 한글's
강사카드 (#49) 32% → 97% 1/1 (was 2) offsets still build up through its stacked forms

Feature matrix against rhwp: tables lines 15% → 100%, SSIM 0.19 → 0.97. The thresholds are raised.

The two exam papers (#51, #65) are two-column pages with equations; those are later items.

Tests

  • PageComposerTests: column widths (absolute, relative, equal); scaling for other formats against 한글's kept widths; row heights and vertical alignment; a spanning cell with an auto-placed neighbour; a table that must not split; splitting between rows with header rows repeated; a row split inside its cells unless it can't split; a nested table; 한글's margin and offset for a table in an empty paragraph.
  • DocumentModelTests: a table starting its paragraph keeps the paragraph's stored line starts, its offset and its outer margin.
  • Engines suite locally: 2336 passed, 0 failed.

🤖 Generated with Claude Code

… borders, page splits

Cells placed on a grid with row and column spans; absolute, relative or equal column widths (other formats' tables
scaled to the text width); padding, vertical alignment, nested tables; rows as high as 한글 sizes them (content
without the last line's spacing); fills and solid, dashed, dotted, dash-dot and double borders; captions. Tables split
across pages by 한글's mode, between rows or inside rows that may split, with header rows repeated. 한글's outer
margin, offset of tables placed at their paragraph, tables sitting in a paragraph's line and tables starting their
paragraph (whose stored lines now still map) are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@KnifeLemon KnifeLemon added the built-in engines Filee: built-in engines (Project 4), on the builtin-engines branch, not released yet label Oct 30, 2026
@github-actions github-actions Bot added the feature New features label Oct 30, 2026
@KnifeLemon
KnifeLemon changed the base branch from engine/page-composer to builtin-engines October 30, 2026 16:02
@KnifeLemon
KnifeLemon merged commit 5df5a61 into builtin-engines Oct 30, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

built-in engines Filee: built-in engines (Project 4), on the builtin-engines branch, not released yet feature New features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant