Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

### 고침

- 쪽 수 추정이 표 칸 안에서 양쪽에 글 자리가 있는 어울림 개체 곁에 빈 줄만 오는 칸도 추정한다. 한/글처럼 빈 줄은 개체 곁에
한 높이 두 조각으로 둔다(곁에 글이 오면 지금처럼 지원 밖). 한/글이 저장한 줄 캐시가 있는 칸에서 그런 두 조각을 줄 둘로
세어 칸을 조각 수만큼 높게 잡던 것도 바로잡았다.
- 쪽 수 추정과 FormFit이 줄 바꿈 뒤 빈 run으로 끝나는 문단의 빈 마지막 줄을 한/글처럼 그 run의 크기로 잡는다(글자보다 작아도).
전에는 작은 run은 무시하고 큰 run은 줄 바꿈 앞 줄까지 키웠다. 끝 run이 더 크면 그 문단의 줄 캐시는 쓰지 않는다.
- 쪽 수 추정이 첫 줄에 붙은 어울림 개체의 세로 위치를 한/글처럼 위 간격 위 문단 맨 위에서 잰다. 전에는 첫 줄 맨 위에서
Expand Down
25 changes: 23 additions & 2 deletions src/hwpx/layout/pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,7 @@ def wrapped_lines(self, paragraphs: list[Any], width: int, tables: bool = False
raise _Unsupported("an object placed top and bottom or square after the text of a paragraph "
"with a layout cache in a cell")
lines, narrow, own = _clear_of(self, fixed, top, shape.prev, anchor, obj, bands, empty, width)
_beside_one_side(narrow, empty)
if narrow and not _cache_lines(paragraph):
raise _Unsupported("text laid out otherwise beside a square-wrapped object in a cell")
else:
Expand All @@ -1035,6 +1036,7 @@ def wrapped_lines(self, paragraphs: list[Any], width: int, tables: bool = False
narrow = found
else:
raise _Unsupported("lines beside a square-wrapped object in a cell that do not settle")
_beside_one_side(narrow, empty)
if narrow and ("\n" in text or style.head):
raise _Unsupported("a paragraph with margins, a label or line breaks beside a square-wrapped "
"object in a cell")
Expand Down Expand Up @@ -1405,6 +1407,12 @@ def _drawn_lines(measure: _Measure, paragraphs: list[Any], width: int | None = N
below = top # where the paragraph's next line would stand
for index, segment in enumerate(segments):
vertpos = int(segment.get("vertpos", 0))
if index and vertpos == int(segments[index - 1].get("vertpos", 0)) \
and int(segment.get("horzpos", 0)) > int(segments[index - 1].get("horzpos", 0)):
follows.append(follows[-1]) # a line's second piece beside an object with text on both sides: at
tops.append(tops[-1]) # the first's height
heights.append(int(segment.get("textheight", segment.get("vertsize", 0))))
continue
follows.append(below)
table = pushing.get(index)
if table is not None and vertpos == _cell_extent(measure, table) + _down(table.find(f"{HP}pos")) \
Expand Down Expand Up @@ -2456,10 +2464,23 @@ def _cell_band(measure: _Measure, obj: Any, top: int, width: int) -> tuple[int,
left = left if left >= _MIN_SIDE and flow != "RIGHT_ONLY" else 0
right = right if right >= _MIN_SIDE and flow != "LEFT_ONLY" else 0
if left and right:
raise _Unsupported(f"text on both sides of {_local(obj)} wrapped square in a cell")
return up, foot, _BothSides(min(left, right))
return up, foot, (left or right) or None


class _BothSides(int):
"""The room beside an object wrapped square in a cell with text on both sides of it (the narrower side's): an
empty line goes beside it, two empty pieces at one height as tall as the line; text there is not followed."""


def _beside_one_side(narrow: dict[int, int], empty: bool) -> None:
"""Text on lines *narrow* beside an object wrapped square in a cell with text on both sides of it (unless
the paragraph is *empty*) is not followed."""

if not empty and any(isinstance(room, _BothSides) for room in narrow.values()):
raise _Unsupported("text on both sides of an object wrapped square in a cell")


def _clear_of(measure: _Measure, metrics: list[tuple[int, int]], top: int, prev: int, anchor: int, obj: Any,
bands: list[tuple[int, int, int | None]], empty: bool, width: int
) -> tuple[list[tuple[int, int, int]], dict[int, int], tuple[int, int, int | None] | None]:
Expand Down Expand Up @@ -2488,7 +2509,7 @@ def _clear_of(measure: _Measure, metrics: list[tuple[int, int]], top: int, prev:
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)
narrow[index] = _BothSides(min(beside)) if any(isinstance(room, _BothSides) for room in beside) else min(beside)
placed.append((y, height, advance))
return placed, narrow, own

Expand Down
Binary file not shown.
5 changes: 5 additions & 0 deletions tests/test_layout_page_estimate.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
# table placed top and bottom 1958 down from it, then three paragraphs: Hancom places the inner table from the
# paragraph's top above its spacing, as in the body, the cell's next paragraph below it from there
"pages_cell_table_down_from_spacing": 4,
# Four times on a page of its own: a table whose cell's empty first paragraph holds a 15000 x 8000 rectangle
# wrapped square 12000 from its left, text on both sides of it, 0 or 2000 down, overlapping the text or not,
# then six empty paragraphs and two of text: the empty lines reaching it go beside it (two empty pieces at one
# height), the table as tall as with room on one side only
"pages_cell_object_on_both_sides_beside_empty_lines": 5,
"pages_square_band_table_as_character_alone": 1, # 47058 wide: beside it all the same, reaching past the room
"pages_square_band_narrow_table_as_character_alone": 1, # 5000 wide: beside it, and the lines after
# ... or text whose lines in the room beside the picture are as wide as it, and an object set as a
Expand Down
Loading