Skip to content

fix(layout): lay out cells around pictures placed top and bottom or square - #532

Merged
airmang merged 2 commits into
mainfrom
fix/page-estimate-wrapped-objects-in-cells
Oct 20, 2026
Merged

airmang merged 2 commits into
mainfrom
fix/page-estimate-wrapped-objects-in-cells

Conversation

@airmang

@airmang airmang commented Oct 20, 2026

Copy link
Copy Markdown
Owner

What

In the page estimate, a table cell paragraph without a layout cache that holds a picture or drawing placed top and bottom (TOP_AND_BOTTOM) or square (SQUARE) from its top, moving with the text, now lays its lines out as Hancom Office 2024 does:

  • The object stands its vertical offset below the top of the line its control falls on (the paragraph laid out the cell's whole width). When that is the paragraph's first line, it is placed from the paragraph's top, above its spacing before. An offset up counts as none.
  • From there on, the lines of that paragraph and of the following paragraphs in the cell keep clear of the object:
    • a line reaching a top-and-bottom object, or a square one that leaves less than 1440 beside it, goes below the object's foot;
    • a line beside a square object stays where it is and breaks again in the room beside it.
  • The cell reaches down to the lowest object's foot, and to the foot of any object in front of or behind the text (fix(layout): grow a cell to hold an object in front of or behind its text #526).
  • When an object may not overlap the text (allowOverlap="0"), an empty paragraph's own line stays beside it.
  • A picture that does not move with the text (flowWithText="0") pushes nothing in a cell. This also holds on the old path.

Before this change, the estimate counted the lines and such objects over one another. A row with text, or with an empty line below such an object, came out lower than Hancom's. Rows then shifted every later body line up.

A paragraph that holds several such objects still counts as it did before, because Hancom stacks the objects that overlap and this change does not follow that.

Cases that are still not estimated (unsupported): text on both sides of a square object, and a paragraph with margins, a label or line breaks beside a square object. The case where a paragraph keeps its layout cache and its control comes after its text is also not estimated.

Tests

  • New fixture tests/fixtures/hancom_saved/pages_wrapped_pictures_in_cells.hwpx (a Hancom Office 2024 save). It has 64 tables set as characters, each with such a picture in its first cell. The fixture varies:
    • where the control sits: before, among or after the text, or alone;
    • first or second paragraph;
    • offsets down and up;
    • outer margins;
    • widths on either side;
    • paragraph spacing;
    • wider line spacing;
    • a picture that stays put.
  • The first commit adds only the fixture and its HANCOM_PAGES entry. In that commit test_without_line_caches_formfit_breaks_the_lines_the_same[pages_wrapped_pictures_in_cells] fails. The second commit makes it pass. The test with caches passed before and still passes.
  • Full suite under -X utf8: same failures as main under the same conditions (environment-only symlink and wheel tests).

Not in this PR

A cell whose paragraphs all keep Hancom's layout cache goes through _drawn_lines. That path has related gaps:

  • it counts a picture that stays put;
  • it measures an object after text from its paragraph's top instead of from its control's line.

These are left for a follow-up.

🤖 Generated with Claude Code

@airmang airmang left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed wrapped_lines, object ownership/anchor selection, cell-band geometry and row metrics at exact head9cbba960a01cea6b7dd7b017602d1f7ff56c68f6. Ran the new wrapped_pictures_in_cells regressions:2 passed,1475 deselected. Found a reproducible unsupported geometry that currently returns a supported layout: opposite-side square objects in different paragraphs lose their horizontal positions when bands are combined. See inline finding. Full CI is still running and the branch conflicts with current main. Holding merge. COMMENT because the authenticated account owns the PR.

Comment thread src/hwpx/layout/pages.py
y, moved = band[1], True
beside = [band[2] for band in around if band[2] is not None and y < band[1] and y + height > band[0]]
if beside:
narrow[index] = min(beside)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Intersect the available horizontal intervals when several square bands touch a line, or reject that case. A band retains only a room width, so min(beside) cannot combine objects occupying opposite edges. Reproduced at this head with a12000-wide cell, a4000-wide left SQUARE/RIGHT_ONLY picture in paragraph1 and a4000-wide right SQUARE/LEFT_ONLY picture in paragraph2, both10000 high and flowWithText=1: wrapped_lines accepts both paragraphs and reports8000-wide rooms for paragraph2 while both bands are active. The common free interval is only[4000,8000], width4000. The guard rejects several objects only within the same paragraph, so it does not cover this case. Preserve left/right interval coordinates and intersect them, or return _Unsupported for simultaneous bands whose room cannot be represented. Add a two-paragraph, opposite-edge regression; the new fixture's one-picture-per-cell cases cannot detect it.

@airmang
airmang force-pushed the fix/page-estimate-wrapped-objects-in-cells branch from 9cbba96 to 2c9021e Compare October 20, 2026 05:22
airmang and others added 2 commits October 20, 2026 17:38
…ls as Hancom does

A Hancom Office 2024 save of 64 tables set as characters, a picture placed top and bottom or square in the
first cell of each: its control before, among or after the text of its paragraph or alone, in the cell's
first or second paragraph, offset down or up, with or without outer margins, beside room of several widths
on either side, with paragraph spacing or wider line spacing. Without line caches the page estimate counts
the lines and the pictures over one another and puts later body lines higher than Hancom does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…quare

In the page estimate, a cell paragraph without a layout cache that holds a picture or drawing placed top and
bottom or square from its top, moving with the text, now lays its lines out as Hancom Office 2024 does. The
object stands its offset below the top of the line its control falls on (or of the paragraph, above its
spacing before, when that is the first line; an offset up counts as none). From there on the lines of that
paragraph and of the next ones keep clear of it: a line reaching a top-and-bottom object, or a square one
leaving less than 1440 beside it, goes below its foot, and a line beside a square object breaks again in the
room beside it. The cell reaches down to the lowest object's foot. An empty paragraph's own line stays
beside an object that may not overlap the text. A picture that does not move with the text pushes nothing
in a cell, as it does not in Hancom.

Before, the estimate counted the lines and such objects over one another, so a row holding text or an empty
line below such an object came out lower than Hancom's. A paragraph holding several such objects (Hancom
stacks those that overlap) still counts as before; text on both sides of one, and paragraphs with margins or
a label beside a square one are left unsupported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@airmang
airmang force-pushed the fix/page-estimate-wrapped-objects-in-cells branch from 2c9021e to b5b3198 Compare October 20, 2026 08:41
@airmang
airmang merged commit 71d6d1c into main Oct 20, 2026
13 checks passed
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