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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

### 고침

- 쪽 수 추정(실험, `estimate_pages`)이 글 문단의 첫 줄에서 아래로 띄운 흐르는 위아래 표를 쪽 끝에서도 따른다.
- 그 줄이 쪽 바닥 위에 들어가지 않으면 줄과 표가 함께 다음 쪽으로 가고, 표는 거기서 띄운 만큼 아래에서 흐른다.
- 줄은 들어가는데 표 윗선이 바닥을 넘거나, 행 단위로 옮기는(TABLE) 표의 첫 행이 들어가지 않으면, 표만 다음 쪽 맨
위에서 시작한다. 문단의 글은 그 줄 아래로 이어지고, 표가 차지하는 쪽에서는 표 아래로 간다.
- 전에는 모두 지원 밖(`a top-and-bottom table offset down from a line at a page end`)이었다. 첫 줄이 아닌 줄에서
띄운 표는 전처럼 지원 밖이다.
- 쪽 수 추정(실험, `estimate_pages`)이 표 칸 안에 위아래나 어울림으로 둔 그림·도형의 높이를 행 높이에 넣는다. 글 없는 칸
문단에서 문단 위를 기준으로 둔 것(글자처럼 두지 않은 것)이면, 칸이 그 개체의 아래 끝(바깥 여백 포함)까지 온다. 전에는 그
개체를 세지 않아 행을 한 줄 높이로 잡았다.
Expand Down
32 changes: 29 additions & 3 deletions src/hwpx/layout/pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@
offset down, it stands that much lower, and the first line reaching it (in that paragraph or the
ones after) and the lines after come below it -- a table flowing with the text flows from there
over the page end, and that line goes below its end (so does the line of a paragraph holding only
another such table, which then flows from there); a flowing table alone in its paragraph starts
another such table, which then flows from there); offset down from a paragraph's first line that
does not fit above the page's foot, it goes on to the next page with the line, and one whose top
falls past the foot, or whose first row moved row by row does not fit under it, starts at the next
page's top while the paragraph's lines go on under its line; a flowing table alone in its paragraph starts
its offset below the paragraph's top, above the paragraph's spacing before (one offset up starts
there), and the next paragraph goes below the table's end or below the paragraph's line and its
own spacing before, whichever is lower;
Expand Down Expand Up @@ -2117,10 +2120,16 @@ def _banded(self, index: int, paras: list[_Para], para: _Para, start: int) -> No
return
if para.band is not None:
band, table = para.band, para.band.table
if not band.line and self.last_vp is not None and start + para.height(0) > self.body:
start = self._next_frame(para, 0, True) # the line goes on to the next page, its table with it
top = start + para.span(0, band.line) + band.offset
if start + para.span(0, band.line) + para.height(band.line) > self.body \
or top + table.above >= self.body or _starts_later(table, top + table.above, self.body):
if start + para.span(0, band.line) + para.height(band.line) > self.body:
raise _Unsupported("a top-and-bottom table offset down from a line at a page end")
if top + table.above >= self.body or _starts_later(table, top + table.above, self.body):
if band.line:
raise _Unsupported("a top-and-bottom table offset down from a line at a page end")
self._band_on_next_page(index, paras, para, table, top, start, broke)
return
frame, end = _flow_table(table, self.frame, top + table.above, self.body)
self._clear_of_paper(self.frame, frame)
self.table_end = max(self.table_end, frame)
Expand Down Expand Up @@ -2155,6 +2164,23 @@ def _banded(self, index: int, paras: list[_Para], para: _Para, start: int) -> No
if self._lay(index, paras, tail, end, False):
self.last_vp, self.last_pitch, self.pending_next = self.out[-1][1], tail.advance(tail.lines - 1), para.next

def _band_on_next_page(self, index: int, paras: list[_Para], para: _Para, table: _FlowTable, top: int,
start: int, broke: bool) -> None:
"""A table offset down from a paragraph's first line whose top falls past the page's foot, or whose first
row (moved row by row) does not fit under it: it starts at the next page's top, and the paragraph's lines
go on under its line, on the pages the table takes below the table."""

frame, end = _flow_table(table, self.frame, top + table.above, self.body)
self._clear_of_paper(self.frame + 1, frame)
taken = range(self.frame + 1, frame + 1)
if frame == self.frame or any(page in self.reserved for page in taken):
raise _Unsupported("a top-and-bottom table offset down from a line at a page end")
self.reserved.update(dict.fromkeys(taken, self.body))
self.reserved[frame] = end + table.below
self.table_end = max(self.table_end, frame)
if self._lay(index, paras, para, start, broke):
self.last_vp, self.last_pitch, self.pending_next = self.out[-1][1], para.advance(para.lines - 1), para.next

def _clear_of_paper(self, first: int, last: int, top: int = 0, end: int | None = None,
below: bool = False) -> None:
"""A table from its anchor line's *top* in frame *first* to *end* in frame *last* (the whole frames
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
8 changes: 8 additions & 0 deletions tests/test_layout_page_estimate.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@
"pages_table_caption_below_ends_100_above_page_foot": 2, # the last row and the caption below end 100
# above the foot: both go on
"pages_table_caption_below_ends_101_above_page_foot": 2, # 101 above it: they stay
"pages_table_offset_down_from_a_line_past_the_foot": 2, # a table top and bottom 1517 down from a line
# that does not fit: both on the next page
"pages_table_offset_down_its_top_past_the_foot": 2, # 2000 down, the line fitting: the table at the
# next page's top, the text after below it
"pages_table_offset_down_its_first_row_past_the_foot": 2, # moved row by row, its first row not fitting:
# the same, a line of the text after on the page


"pages_table_cell_holding_a_drawing_top_and_bottom": 1, # a cell paragraph holding only a rectangle 10000
# tall placed top and bottom from it: the row is
# as tall as it with the cell's margins
Expand Down
Loading