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 @@ -99,6 +99,9 @@
- 탭 정의에 자기 탭 위치나 자동 탭이 있는 문단은 전처럼 잰다.
- 쪽 수 추정에서 강제 줄 바꿈 다음 줄은 첫 줄이 아니다. 들여쓰기를 빼지 않고 다른 줄의 폭으로 잰다. 전에는 첫 줄 폭으로
재서, 들여쓴 문단에서 줄이 하나 더 생길 수 있었다.
- FormFit과 쪽 수 추정이 텍스트 내보내기가 쓰지 않는 번호 형식(`KOREAN_DIGIT`, `HANGUL` 등)의 문단 번호를 만나도
멈추지 않는다. 한/글이 재는 번호(`useInstWidth`)이면 그 숫자를 한글 한 글자 폭으로 잰다. 전에는 번호가 자기 글자
모양을 가진 문단에서 `KeyError`가 났다.
- `.hwp`를 열 때 그림의 투명도와 반전을 한/글이 읽는 자리에서 읽는다. 한/글은 그림 레코드의 투명도를 그림 원래 크기
뒤 마지막 바이트에서 읽고, 바이너리 항목 번호 뒤 바이트는 읽지 않는다(저장할 때 0으로 쓴다). 전에는 그 바이트를
투명도로 옮겨, 거기에 255가 든 문서의 그림이 HWPX에서 보이지 않았다. 반전(`hp:pic@reverse`)은 그림 개체 속성의
Expand Down
7 changes: 5 additions & 2 deletions src/hwpx/form_fit/measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -2252,10 +2252,13 @@ def fill(match: "re.Match[str]") -> str:
form = (head.get("numFormat") if head is not None else None) or "DIGIT"
if not measured:
return "1" if form in _ASCII_NUMBER_FORMATS else "\uac00"
from ..tools.exporter import _number_text
from ..tools.exporter import _NUMBER_FORMATS, _number_text

start = int(_style_number(head.get("start") if head is not None else None, 1.0))
return _number_text(start, form) if key != "N" else f"{start}."
if key == "N":
return f"{start}."
# a format the text export does not write (KOREAN_DIGIT, HANGUL, ...) counts as one syllable
return _number_text(start, form) if form in _NUMBER_FORMATS else "가"

return re.sub(r"\^(\d+|N)", fill, paragraph_head.text or ""), attrs

Expand Down
23 changes: 23 additions & 0 deletions tests/test_layout_page_estimate.py
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,29 @@ def test_without_line_caches_formfit_breaks_the_lines_the_same(name: str) -> Non
_assert_like_hancom(estimate_pages(_without_caches(data)), data, HANCOM_PAGES[name])


@pytest.mark.parametrize("number_format", ["KOREAN_DIGIT", "HANGUL"])
def test_a_number_label_in_a_format_the_text_export_does_not_write_is_estimated(number_format: str) -> None:
# The bullet and number labels above, every number measured, in a character shape of its own and in a
# format of Hancom's own documents that the text export does not write: such a number counts as a syllable
# instead of failing the estimate.
out = io.BytesIO()
with zipfile.ZipFile(io.BytesIO((FIXTURES / "pages_bullet_and_number_labels.hwpx").read_bytes())) as source, \
zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED) as target:
for info in source.infolist():
payload = source.read(info.filename)
if info.filename == "Contents/header.xml":
payload = re.sub(rb'numFormat="[A-Z_]+"', f'numFormat="{number_format}"'.encode(), payload)
payload = re.sub(rb'useInstWidth="\w+"', b'useInstWidth="1"', payload)
payload = re.sub(rb'(<hh:paraHead [^>]*)charPrIDRef="\d+"', rb'\1charPrIDRef="0"', payload)
target.writestr(info, payload)

for source_bytes in (out.getvalue(), _without_caches(out.getvalue())):
estimate = estimate_pages(source_bytes)

assert estimate.unsupported == ()
assert estimate.pages >= 1


def test_an_unsplit_table_without_room_goes_on_alone() -> None:
# The table above, 63000 tall, set not to split: with no room below the line's top, it goes alone to the
# next page's top and the paragraph's lines, and those after, stay where they stood on the first page.
Expand Down
Loading